一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
这次给大家带来一个用requestAnimationFrame的抛物线运动小动画,先上效果图:
原理
主要是利用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 回调,用法跟clearTimeout及clearInterval是一样的
到这里,整体的逻辑就完成啦!
大家有问题和错误都可以在评论区中指出,感谢~