` ````
<canvas id="c"></canvas>
<p>
Current Angle: <span id="angle"></span><br />
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>
```

` ````
body {
background: #ddd;
font: 100%/1.5 monospace;
}
canvas {
background: #fff;
display: block;
}
p {
max-width: 40em;
padding-left: 1.5em;
}
```

` ````
var c = document.getElementById( 'c' ),
ctx = c.getContext( '2d' ),
cw = c.width = 300,
ch = c.height = 200,
joint = {
x: cw / 2,
y: ch / 2,
length: 50,
angle: 0,
targetAngle: 0,
easing: 0.05,
velocity: 0,
maxAccel: 0.01
},
angleElem = document.getElementById( 'angle' );
targetAngleElem = document.getElementById( 'target-angle' );
function clip(x, min, max) {
return x < min ? min : x > max ? max : x
}
function step() {
requestAnimationFrame( step );
ctx.clearRect( 0, 0, cw, ch );
// ease the current angle to the target angle
// first, adjust joint.angle to cross boundary properly
var dtheta = joint.targetAngle - joint.angle;
if (dtheta > Math.PI) joint.angle += 2*Math.PI;
else if (dtheta < -Math.PI) joint.angle -= 2*Math.PI;
// then, cap acceleration to eliminate jerkiness
var targetVel = ( joint.targetAngle - joint.angle ) * joint.easing;
joint.velocity = clip(targetVel,
joint.velocity - joint.maxAccel,
joint.velocity + joint.maxAccel);
// finally, move with clipped velocity
joint.angle += joint.velocity;
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 ) {
// get angle from joint to mouse
var dx = e.clientX - joint.x,
dy = e.clientY - joint.y;
joint.targetAngle = Math.atan2( dy, dx );
}, false );
step();
```

999px

Loading
..................