我已经在这个问题上研究了一段时间,但似乎找不到解决方案(我和三角函数不是朋友)。 我正在尝试构建一个元素,用户可以“抓住”并旋转。我已经让它工作了,除了最后一个功能我似乎无法解决: http://codepen.io/megakoresh/pen/WbLLzZ?editors=001
(很长,但我只问snapTo()函数应该如何工作)。
我想要的是对象根据increments
值捕捉度数。这意味着如果snap==true
,则代码应计算释放鼠标时最接近的估计target
,并基于旋转方向平滑旋转对象到该target
旋转:
由于对象被“抓住”,所以我计算了鼠标按下时对象的当前旋转偏移量,因此它不会只是跟随鼠标捕捉。
因此,在这种情况下,用户顺时针旋转对象,并在对象旋转介于90°和45°之间时释放鼠标。由于方向(由angle
变量的符号确定)是正的,因此目标将在当前旋转之后。
任务是计算该目标,然后平滑地将对象旋转到该目标。
我编写的函数基于autoSpin()函数(当spin==false
时执行),它采用翻转的时间指数乘数delta
(根据自鼠标释放以来的时间经过计算)。随着时间的推移,delta
将沿着翻转指数减少,因此角度会减慢。
有一个spinTo()函数,请不要评判我,我觉得它非常愚蠢:
function snapTo() {
var elapsed, delta;
increments = (typeof increments === 'number') ? Math.floor(increments) : 4;
var ia = 360 / increments; //increment angle - snapping points should occur "every ia degrees"
if (Math.abs(angle % ia) > 0) { //if user turned for more than 1 increment
var a = lastRot % ia; //check the distance from
if (angle > 0){ //positive direction
amplitude = 50; //if snapping is on, force amplitude
target = (lastRot - a) + ia;
}
if (angle < 0){ //negative direction
amplitude = -50;
target = lastRot - a;
}
} else { //cancel the rotation
target = rotation;
}
elapsed = Date.now() - timestamp; //time passed since mouse was released
delta = -amplitude * Math.exp(-elapsed / timeConstant); //the greater the time from mouse release, the smaller this value
if (delta > 0.5 || delta < -0.5) { //while delta is decreasing...
rotate(target - delta - offset);
snapFrame = requestAnimationFrame(snapTo); //keep rotation
} else {
rotate(target - offset); //when enough time passes (based on timeConstant), make one final rotation and stop
}
}
我做错了什么?