Sztuka polega na tym, aby pamiętać, że kąty (przynajmniej w przestrzeni euklidesowej) są okresowe o 2 * pi. Jeśli różnica między bieżącym kątem a kątem docelowym jest zbyt duża (tzn. Kursor przekroczył granicę), po prostu dostosuj aktualny kąt, odpowiednio dodając lub odejmując 2 * pi.
W takim przypadku możesz spróbować wykonać następujące czynności: (Nigdy wcześniej nie programowałem w JavaScript, więc wybacz mój styl kodowania).
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;
EDYCJA : W tej implementacji zbyt szybkie przesuwanie kursora wokół środka stawu powoduje jego szarpnięcie. Jest to zamierzone zachowanie, ponieważ prędkość kątowa złącza jest zawsze proporcjonalna do dtheta
. Jeśli takie zachowanie jest niepożądane, problem można łatwo rozwiązać, nakładając kołpak na przyspieszenie kątowe stawu.
Aby to zrobić, musimy śledzić prędkość połączenia i nałożyć maksymalne przyspieszenie:
joint = {
// snip
velocity: 0,
maxAccel: 0.01
},
Następnie dla naszej wygody wprowadzimy funkcję obcinania:
function clip(x, min, max) {
return x < min ? min : x > max ? max : x
}
Teraz nasz kod ruchu wygląda tak. Najpierw obliczamy dtheta
jak poprzednio, dostosowując joint.angle
w razie potrzeby:
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;
Następnie, zamiast natychmiastowego przesunięcia stawu, obliczamy prędkość docelową i używamy jej clip
do wymuszenia jej w dopuszczalnym zakresie.
var targetVel = ( joint.targetAngle - joint.angle ) * joint.easing;
joint.velocity = clip(targetVel,
joint.velocity - joint.maxAccel,
joint.velocity + joint.maxAccel);
joint.angle += joint.velocity;
Zapewnia to płynny ruch, nawet przy zmianie kierunku, podczas wykonywania obliczeń tylko w jednym wymiarze. Ponadto umożliwia niezależną regulację prędkości i przyspieszenia złącza. Zobacz demo tutaj: http://codepen.io/anon/pen/HGnDF/