Хитрість полягає в тому, щоб пам’ятати, що кути (принаймні в евклідовому просторі) періодичні на 2 * пі. Якщо різниця між кутом струму та цільовим кутом занадто велика (тобто курсор перейшов межу), просто відрегулюйте поточний кут, додавши або віднімаючи 2 * пі відповідно.
У цьому випадку ви можете спробувати наступне: (Я ніколи раніше не програмував у Javascript, тому пробачте мій стиль кодування.)
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 : У цій реалізації занадто швидко переміщення курсору по центру суглоба призводить до його ривків. Це призначена поведінка, оскільки кутова швидкість суглоба завжди пропорційна dtheta. Якщо така поведінка небажана, проблему можна легко усунути, поставивши ковпачок на кутове прискорення суглоба.
Для цього нам потрібно буде стежити за швидкістю суглоба і накласти максимальне прискорення:
joint = {
// snip
velocity: 0,
maxAccel: 0.01
},
Тоді для нашої зручності ми введемо функцію відсікання:
function clip(x, min, max) {
return x < min ? min : x > max ? max : x
}
Тепер наш код руху виглядає приблизно так. Спочатку ми обчислюємо, dthetaяк і раніше, коригуючи joint.angleпри необхідності:
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;
Тоді, замість того, щоб миттєво рухати суглоб, ми обчислюємо цільову швидкість і використовуємо clipдля того, щоб примусити її в межах нашого прийнятного діапазону.
var targetVel = ( joint.targetAngle - joint.angle ) * joint.easing;
joint.velocity = clip(targetVel,
joint.velocity - joint.maxAccel,
joint.velocity + joint.maxAccel);
joint.angle += joint.velocity;
Це створює плавний рух навіть при переключенні напрямків, виконуючи обчислення лише в одному вимірі. Крім того, це дозволяє самостійно регулювати швидкість і прискорення суглоба. Дивіться демонстрацію тут: http://codepen.io/anon/pen/HGnDF/