Хитрість полягає в тому, щоб пам’ятати, що кути (принаймні в евклідовому просторі) періодичні на 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/