CodePen

HTML

            
              <canvas id="c"></canvas>
<p>
  Current Angle: <span id="angle"></span><br />
  &nbsp;Target Angle: <span id="target-angle"></span><br />
</p>
<p>I'm trying to have the joint rotate smoothly around the center of the canvas, toward the angle of mouse pointer. What I have works, but I want it to animate the shortest distance possible, to get to the mouse angle. The problem occurs when the value loops around at the horizontal line (3.14 and -3.14). Mouseover that area to see how the direction switches and it takes the long way back around.</p>
<p>Relevant lines of code are 20 and 48. Any ideas on how to get this working?</p>
            
          
!

CSS

            
              body {
  background: #ddd;
  font: 100%/1.5 monospace;
}

canvas {
  background: #fff;
  display: block;
}

p {
  max-width: 40em;
  padding-left: 1.5em;
}
            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              var c = document.getElementById( 'c' ),
    ctx = c.getContext( '2d' ),
    cw = c.width = 300,
    ch = c.height = 200,
    mx = 0,
    my = 0,
    joint = {
      x: cw / 2,
      y: ch / 2,
      length: 50,
      angle: 0,
      targetAngle: 0,
      easing: 0.05
    },
    angleElem = document.getElementById( 'angle' );
    targetAngleElem = document.getElementById( 'target-angle' );

function step() {
  requestAnimationFrame( step );
  ctx.clearRect( 0, 0, cw, ch );
  
  // ease the current angle to the target angle
  /*joint.angle += ( joint.targetAngle - joint.angle ) * joint.easing;*/
  
  // get normalised direction from joint to mouse
  var dx = mx - joint.x,
      dy = my - joint.y,
      len = Math.sqrt(dx * dx + dy * dy);
      dx /= len ? len : 1.0; dy /= len ? len : 1.0;
  // get current direction
  var dirx = Math.cos(joint.angle),
      diry = Math.sin(joint.angle);
  // ease the current direction to the target direction
  dirx += (dx - dirx) * 0.1;
  diry += (dy - diry) * 0.1;

  joint.angle = Math.atan2(diry, dirx);
  joint.targetAngle = Math.atan2(dy, dx);
  
  ctx.save();
  ctx.beginPath();
  ctx.translate( joint.x, joint.y + 0.5 );
  ctx.rotate( joint.angle );
  ctx.moveTo( 0, 0 );
  ctx.lineTo( joint.length, 0 );
  ctx.lineWidth = 5;
  ctx.stroke();
  ctx.restore();
  
  ctx.beginPath();
  ctx.arc( joint.x, joint.y, 10, 0, Math.PI * 2 );
  ctx.fill();
  
  ctx.beginPath();
  ctx.moveTo( 0, joint.y + 0.5 );
  ctx.lineTo( joint.x, joint.y + 0.5 );
  ctx.lineWidth = 1;
  ctx.stroke();
  
  angleElem.innerHTML = joint.angle.toFixed( 3 );
  targetAngleElem.innerHTML = joint.targetAngle.toFixed( 3 );
}

window.addEventListener( 'mousemove', function( e ) {
  mx = e.clientX,
  my = e.clientY;  
}, false );

step();
            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................