requestAnimationFrame实现小球抛物线运动

946 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

这次给大家带来一个用requestAnimationFrame的抛物线运动小动画,先上效果图:

ball.gif

原理

主要是利用requestAnimationFrame的特性,在每一帧中更新小球位置,而小球的位置由水平方向的速度,及垂直方向的加速度决定。

那么我们直接开整

首先初始化一些要用的变量:

// 小球起始位置
let XStart = 100,
YStart = 100,
// 抛物线的开始点坐标 结束点坐标
XEnd = document.body.clientWidth,
YEnd = document.body.clientHeight;
let Time = 200;  //运行时间,
let XSpeed = (XEnd - XStart) / Time; // 水平方向上的速度Δx=vt
let A = 2 * (YEnd - YStart)/(Time * Time);  //代入加速度运算公式Δx=1/2at^2
let animaId,ballInstant; // requestAnmitionFrameId(用于clear),小球dom实例(用于停止)
let nowX,nowY,loop // 当前位置,循环次数

上面的变量包括了小球的初始位置,终点位置,动画的整体时间(注意这里的时间单位不是ms,而是requestAnimationFrame调用的次数)

小球的水平速度Δx=vt计算得出,垂直加速度由Δx=Δx=vt+1/2at^2得出

然后就是小球运动时的变量,当前X,Y位置以及当前循环次数(Δt)

然后,设置小球的初始状态:

初始状态包括设置小球的dom实例、样式,将运动变量设置为初始状态:

const init = ()=>{
  // js动态创建对象
  if(ballInstant){ // 如果已存在小球实例,先清空
    stop()
  }
  ballInstant = document.createElement('div');
  ballInstant.className = 'ball';
  document.body.appendChild(ballInstant);
  ballInstant.style.top = YStart + 'px';
  ballInstant.style.left = XStart + 'px';
  loop= 0;
  nowX = XStart; //当前X
  nowY = YStart; //当前Y
 }

最重要的,让小球动起来

代码如下:

/ 在函数内部再调用函数自身
let move = () => {
  animaId = requestAnimationFrame(()=>{
  ballInstant.style.top = nowY + 'px';
  ballInstant.style.left = nowX + 'px';
  nowX += XSpeed; // x = vt
  nowY += A * loop; // v = at
  if(nowY >= YEnd || nowX >= XEnd){
    stop()
  }
  move();
  loop++;
})
}

其实就是在每一帧的回调里调用自身,然后小球的位置是由速度累加而成的。

在一个时间单位(也就是一次requestAnimationFrame的调用)中,小球在水平方向上移动了1单位水平速度,在垂直方向上移动了at,t其实就是时间单位,这里手动统计一下,每次调用requestAnimationFrame就+1;

当小球运动到了终点后,就设置停止;

停止代码如下:

stop = ()=>{ // 停止
  ballInstant.parentNode.removeChild(ballInstant);
  ballInstant = null;
  cancelAnimationFrame(animaId) 
}

主要逻辑就是移除掉小球dom,然后再根据id移除掉requestAnimationFrame 回调,用法跟clearTimeoutclearInterval是一样的

到这里,整体的逻辑就完成啦!

参考完整代码

演示地址

大家有问题和错误都可以在评论区中指出,感谢~