javascript - 平滑地将可旋转的对象捕捉到一定程度

标签 javascript animation rotation trigonometry

我已经研究这个问题一段时间了,但似乎找不到解决方案(我不是三 Angular 函数的 friend )。 我正在尝试构建一个用户可以“抓取”然后旋转的元素。我让它工作,除了最后一个我似乎无法弄清楚的功能: http://codepen.io/megakoresh/pen/WbLLzZ?editors=001

(它很长,但我只是在询问 snapTo() 函数应该如何工作)。

我想要的是根据 increments 值将对象捕捉到度数。这意味着如果 snap==true,代码应该计算最接近鼠标释放点的估计 target,并根据旋转方向平滑地旋转反对那个 target 旋转: enter image description here 由于对象被“抓取”,我计算了 mousedown 到对象当前旋转的偏移量,这就是它的来源,所以它不只是捕捉到鼠标。

因此在这种情况下,用户顺时针旋转对象并在对象旋转介于 90° 和 45° 之间时释放鼠标。由于方向(由 angle 变量的符号标识)为正,因此目标将在当前旋转之后。

任务是计算该目标,然后将对象平滑地旋转到它。

我为它编写的函数基于 autoSpin() 函数(在 spin==false 时执行),它采用翻转时间指数乘数 delta (从松开鼠标后耗时计算)。 delta 将随着时间的推移沿翻转指数减小,因此 Angular 变慢。

有 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
    }     
  }

我做错了什么?

最佳答案

*叹息 好吧,我必须自己想办法。如果有人想做这种事情,这里有一种方法:

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...
    }
  }

所以在这里

  • elapsed 是鼠标松开后耗时
  • increments 是用户提供的参数:会有多少个捕捉点
  • ia 是计算的增量度数:360/increments
  • last 是记录在 mouseup 事件上的 Angular - 图表中的“当前旋转”。它包括偏移量(在我的代码中,它只是 rotation 在发布点的“快照”,然后它的符号也会反转,因为在 DOM 中坐标系是 y 翻转的,我不不喜欢和那个一起工作)。
  • alast 比上一个最近的增量点大多少。
  • diff 是图表上的“目标” - final rotation 和 last
  • 之间的区别
  • ease 只是根据您的缓动函数而变化的值,您可以根据该值继续调用 RAF 或完成动画。
  • timeConstant 是以毫秒为单位的动画持续时间。你可以有这个或没有,取决于你的缓动公式

一般阅读的好资源:Understanding Easing Functions

还有 Desmos graphing calculator非常适合开发缓动公式。

哦,如果有人想知道,似乎不可能将任何类型的非时间相关参数传递给 RAF 回调函数。如果我这样做,似乎会破坏它。所以唯一的解决方案是在代码的其他地方定义 increments 值。

Codepen of the working function

谁有更好的解决方案,我满眼都是。

关于javascript - 平滑地将可旋转的对象捕捉到一定程度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29327576/

相关文章:

javascript - 从 cookie javascript 捕获特定值

javascript - 将数据保存在数据库问题中,在控制台上收到 NULL

javascript - 为什么在这个 JavaScript 动画中,某些元素会去到奇怪的地方?

javascript - 动画不适用于伪元素? IE10

java - 获取旋转矩形的角

algorithm - 给出水平翻转和垂直翻转的旋转是什么?

javascript - Facebook API 没有响应

javascript - 当我单击过滤器菜单时,同位素过滤器图像奇怪的动画和晃动几秒钟

matlab - 在 Matlab 中使用 hgtransform 命令绘制 3D 动画图

java - java中使用Slider旋转对象