L'astuce consiste à se rappeler que les angles (au moins dans l'espace euclidien) sont périodiques de 2 * pi. Si la différence entre l'angle actuel et l'angle cible est trop grande (c'est-à-dire que le curseur a franchi la limite), ajustez simplement l'angle actuel en ajoutant ou en soustrayant 2 * pi en conséquence.
Dans ce cas, vous pouvez essayer ce qui suit: (Je n'ai jamais programmé en Javascript auparavant, alors pardonnez mon style de codage.)
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;
joint.angle += ( joint.targetAngle - joint.angle ) * joint.easing;
EDIT : Dans cette implémentation, déplacer le curseur trop rapidement autour du centre de l'articulation le fait bouger. C'est le comportement recherché, car la vitesse angulaire du joint est toujours proportionnelle à dtheta
. Si ce comportement n'est pas souhaité, le problème peut être facilement résolu en plaçant un capuchon sur l'accélération angulaire du joint.
Pour ce faire, nous devons suivre la vitesse de l'articulation et imposer une accélération maximale:
joint = {
// snip
velocity: 0,
maxAccel: 0.01
},
Ensuite, pour notre commodité, nous allons introduire une fonction d'écrêtage:
function clip(x, min, max) {
return x < min ? min : x > max ? max : x
}
Maintenant, notre code de mouvement ressemble à ceci. Tout d'abord, nous calculons dtheta
comme précédemment, en ajustant joint.angle
si nécessaire:
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;
Ensuite, au lieu de déplacer le joint immédiatement, nous calculons une vitesse cible et l'utilisons clip
pour la forcer dans notre plage acceptable.
var targetVel = ( joint.targetAngle - joint.angle ) * joint.easing;
joint.velocity = clip(targetVel,
joint.velocity - joint.maxAccel,
joint.velocity + joint.maxAccel);
joint.angle += joint.velocity;
Cela produit un mouvement fluide, même lors du changement de direction, tout en effectuant des calculs dans une seule dimension. De plus, il permet de régler indépendamment la vitesse et l'accélération du joint. Voir la démo ici: http://codepen.io/anon/pen/HGnDF/