Javascript 平滑地将可旋转对象捕捉到度
我对这个问题已经研究了一段时间,但似乎找不到解决办法(我不是三角学的朋友)。 我试图构建一个用户可以“抓取”然后旋转的元素。我有它的工作,除了最后一个功能,我似乎不明白: (虽然很长,但我只是想问一下snapTo()函数应该如何工作) 我想要的是基于Javascript 平滑地将可旋转对象捕捉到度,javascript,animation,rotation,trigonometry,Javascript,Animation,Rotation,Trigonometry,我对这个问题已经研究了一段时间,但似乎找不到解决办法(我不是三角学的朋友)。 我试图构建一个用户可以“抓取”然后旋转的元素。我有它的工作,除了最后一个功能,我似乎不明白: (虽然很长,但我只是想问一下snapTo()函数应该如何工作) 我想要的是基于增量值将对象捕捉到度。这意味着,如果snap==true,则代码应计算距离鼠标释放点最近的估计目标s,并根据旋转方向将对象平滑旋转到该目标旋转: 因为对象是“抓取”的,所以我计算了mousedown到对象当前旋转的偏移量,这就是它的来源,所以它不只
增量值将对象捕捉到度。这意味着,如果snap==true
,则代码应计算距离鼠标释放点最近的估计目标
s,并根据旋转方向将对象平滑旋转到该目标
旋转:
因为对象是“抓取”的,所以我计算了mousedown到对象当前旋转的偏移量,这就是它的来源,所以它不只是捕捉到鼠标
因此,在这种情况下,用户顺时针旋转对象,并在对象旋转介于90°和45°之间时释放鼠标。由于方向(由角度
变量的符号标识)为正,目标将在当前旋转之后
任务是计算该目标,然后平滑地将对象旋转到该目标
我为它编写的函数基于by autoSpin()函数(在spin==false
时执行),它采用翻转的时间指数乘数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
}
}
函数snapTo(){
var,delta;
增量=(增量类型=='number')?数学地板(增量):4;
var ia=360/增量;//增量角度-捕捉点应“每隔ia度”出现
如果(Math.abs(角度%ia)>0){//如果用户转动超过1个增量
var a=lastRot%ia;//检查距离
如果(角度>0){//正方向
振幅=50;//如果启用捕捉,则强制振幅
目标=(lastRot-a)+ia;
}
如果(角度<0){//负方向
振幅=-50;
target=lastRot-a;
}
}否则{//取消旋转
目标=旋转;
}
经过=日期。现在()-timestamp;//鼠标释放后经过的时间
delta=-amplitude*Math.exp(-appeased/timeConstant);//鼠标释放的时间越长,该值越小
如果(δ>0.5 | |δ<-0.5){//,而δ在减小。。。
旋转(目标-增量-偏移);
snapFrame=requestAnimationFrame(snapTo);//保持旋转
}否则{
旋转(目标-偏移);//当经过足够的时间(基于时间常数)时,进行最后一次旋转并停止
}
}
我做错了什么?*le叹气
好吧,我得自己想办法。如果有人想做这类事情,这里有一种方法:
function snapTo() {
var elapsed, ease, diff;
increments = (typeof increments === 'number') ? Math.floor(increments) : 4;
var ia = 360 / increments; //increment angle - this is how large each increment will be
var a = last % ia; //check the distance from point of mouse release to the previous increment
if (movement>0) {
elapsed = Date.now() - timestamp; //time passed since mouse was released
ease = 1 - Math.exp((-3*elapsed)/timeConstant); //your easing function formula goes here
if(a > ia/2) { //if halfway through the increment...
target = (last - a) + ia; //target next increment
}
else { //else revert to previous increment to the point of mouse release
target = last - a;
}
diff = target - last; //difference between target and rotation at time of mouse release
if(ease < 0.95){ //this depends on your easing formula
rotate(last+diff * ease);
requestAnimationFrame(snapTo); //don't forget to RAF
} else { //and for your final frame...
rotate(last+diff); //make it snappy :P
}
console.log(last); //traces of debugging were found in this derelict question...
}
}
函数snapTo(){
变量、易用性、差异性;
增量=(增量类型=='number')?数学地板(增量):4;
var ia=360/增量;//增量角度-这是每个增量的大小
var a=last%ia;//检查从鼠标释放点到上一个增量的距离
如果(移动>0){
经过=日期。现在()-timestamp;//鼠标释放后经过的时间
ease=1-Math.exp(-3*appeased)/timeConstant);//您的easing函数公式如下
如果(a>ia/2){//如果增量已过一半。。。
target=(last-a)+ia;//目标下一个增量
}
else{//else恢复到鼠标释放点之前的增量
目标=最后一个-a;
}
diff=target-last;//释放鼠标时目标和旋转之间的差异
如果(ease<0.95){//这取决于您的ease公式
旋转(最后+差异*轻松);
requestAnimationFrame(snapTo);//别忘了RAF
}否则{//对于最后一帧。。。
旋转(上一个+diff);//使其快速:P
}
console.log(last);//在这个被忽略的问题中找到了调试的痕迹。。。
}
}
所以在这里
是鼠标释放后经过的时间appead
是用户提供的参数:将有多少捕捉点增量
是以度为单位计算的增量:360/ia
增量
是记录在图中的last
事件-“当前旋转”上的角度。它包括偏移量(在我的代码中,它只是发布点旋转的“快照”,然后在符号中也会反转,因为在DOM中坐标系是y翻转的,我不喜欢使用它)李>mouseup
是a
比上一个最近的增量点大多少最后一个
是图表上的“目标”-最终旋转和diff
last
只是根据您的easing函数更改的值,您可以根据该值继续调用RAF或完成动画ease
是动画所需时间的毫秒数。你可以有或没有,这取决于你的放松公式timeConstant
增量
值
任何人有更好的解决办法,我全神贯注