requestAnimationFrame的动画速度调整
🔍
requestAnimationFrame
的默认帧数是根据浏览器的默认刷新率来确定的,目前大多数浏览器的刷新率为每秒60帧(60 frames per second,简称FPS
),因此,如果你使用requestAnimationFrame
来执行动画或进行其他涉及动态更新的操作时,它的默认帧数就是每秒60帧,也就是16ms刷新一帧。
下面我们看一段代码,实现一个移动方块,在不控制帧率的情况下,这个动画的持续时间我们是可以计算得出的。假设例子中浏览器的刷新率是60FPS,这个方块的总移动距离是400px(父元素宽500 - 子元素方块宽100,那么动画的持续时间:400 / 60 = 6.66秒
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.box {
width: 500px;
height: 100px;
border: 2px solid #FFE9AE;
}
.box__item {
height: 100%;
width: 100px;
background-image: linear-gradient(35deg, #FFB3B3, #FFDBA4);
}
</style>
</head>
<body>
<div class="box">
<div class="box__item"></div>
</div>
</body>
</html>
<script>
const boxItem = document.querySelector(".box__item");
const box = document.querySelector(".box");
// 方块的移动目标距离: 父元素 - 子元素 - 父元素的左右边框宽度
const targetPosition = box.getBoundingClientRect().width - boxItem.getBoundingClientRect().width - 4;
const initialPosition = 0;
let currentPosition = initialPosition
function updataAnimate() {
currentPosition += 1;
boxItem.style.transform = `translateX(${currentPosition}px)`;
if (currentPosition < targetPosition) {
// 动画未完成,继续下一帧
requestAnimationFrame(updataAnimate);
}
}
requestAnimationFrame(updataAnimate)
</script>
下面我们控制这个动画的持续时间为2秒
,将上面代码稍微改动一下
const boxItem = document.querySelector(".box__item");
const box = document.querySelector(".box");
// 方块的移动目标距离: 父元素 - 子元素 - 父元素的左右边框宽度
const targetPosition = box.getBoundingClientRect().width - boxItem.getBoundingClientRect().width - 4;
// 定义动画初始位置
const initialPosition = 0;
// 设置2秒完成该动画
const animationDuration = 2000;
let startTime;
function updataAnimate(timestamp) {
// 记录动画开始时间
if(!startTime) startTime = timestamp;
// 计算动画的经过时间
const elapsedTime = timestamp - startTime;
// 计算动画的进度
const progress = Math.min(elapsedTime / animationDuration, 1);
// 获取当前位置
const currentPosition = initialPosition + (targetPosition - initialPosition) * progress;
// 更新动画
boxItem.style.transform = `translateX(${currentPosition}px)`;
if(progress < 1) requestAnimationFrame(updataAnimate)
}
requestAnimationFrame(updataAnimate)
在上述代码中,我们利用startTime
和timestamp
计算出动画经过时间,然后计算出动画的进度,根据进度更新当前位置,如果进度值小于1则继续请求下一帧。
转载自:https://juejin.cn/post/7239249100335415357