Earlier, I was trying to find out how to rotate a line around a pivot using p5.js, and I played with the code a little bit to make the line point towards the mouse using the atan2
function. It worked fine, and I decided to see what it would look like if I used linear interpolation (lerp
) to make the animation look smoother. What was weird is that it seemed once the line passed a certain point, it jumped to the other side instead of just moving to that point.
Here’s the code I’m having the issue with:
let angle = 0;
let rot = 0;
function setup() {
createCanvas(600, 300);
}
function draw() {
let v1 = createVector(width / 2 - 50, height / 2);
let v2 = createVector(width / 2 + 50, height / 2);
background(255);
stroke(0);
strokeWeight(4);
rot = lerp(rot, atan2(mouseY - v1.y, mouseX - v1.x), 0.1);
push();
translate(v1.x, v1.y);
rotate(rot);
translate(-v1.x, -v1.y);
let r0 = line(v1.x, v1.y, v2.x, v2.y);
strokeWeight(10);
let p1 = point(v1.x, v1.y);
let p2 = point(v2.x, v2.y);
pop();
}
How can I make this animation look smooth, without the weird jumping?
2
Answers
The issue is because
atan2
returns value between-Math.PI
to+Math.PI
so there is a jump where the linear interpolation fails for the expressiontarget_angle = atan2(mouseY - v1.y, mouseX - v1.x)
.That’s why, in order to make the shortest path between current
rot
totarget_angle
we should normalize the difference between so that the distance to cover itsabs
value should be less thanMath.PI
(half a circle)This is a variation on IT goldman’s nice answer(+1) with the same principle @ggorlen metioned. (I was familiar with the idea from actionscript 3 days from GreenSock’s ShortRotationPlugin). Credits go to them.
This is the mixture of the above: the key difference is avoiding the blocking
while
loops (which I don’t generally recommend).