requestAnimationFrame的作用及使用

我们平时实现JavaScript动画效果时离不开setInterval或者setTimeout函数,这两个函数本质上相同的。

以setInterval为例,他的作用是以相同的时间间隔执行某个操作,这个时间可以自定义,利用这个特性我们就可以让然也元素跑起来。

可是这个函数有个毛病,他和显示器的刷新频率无法对应。比如说显示器每100毫秒刷新一次,setInterval函数设置的间隔执行也是100毫秒,可是我们没有办法保证显示频率刷新的时候setInterval的操作正好被执行,虽然它们的相对执行时间相同,可绝对时间不一定一致,所以setInterval制作动画的时候会出现丢帧和动画效果生硬不连贯等情况。

requestAnimFrame是H5新标准上的东西,在PC浏览器上会出现兼容问题,在移动端浏览器中可以任意使用。 次函数会接受一个回调函数,当浏览器的显示频率刷新的时候,此函数会被执行。

window.requestAnimationFrame(function( time){
    //显示频刷新的时候被执行
});

回调函数有一个参数,是一个相对的时间毫秒值,表示当前的刷新时间。

requestAnimationFrame的回调函数并不能被重复调用,这点和setInterval不同,它和setTimeout类似,回调函数只能被调用一次,只不过setTimeout可以自定义调用时间, requestAnimationFrame的调用时间则是跟着系统的刷新频率走的,所以在实现动画的时候,setTimeout比requestAnimationFrame更加灵活, requestAnimationFrame比setTimeout表现效果更加优秀。

以在3000毫秒内移动1500px距离的动画为例

setTimeout的实现方式

<div id="div" style="width:100px; height:100px; background-color:#000; position: absolute;left:0; top:0;">
    
</div>

<script type="text/javascript">
let divEle = document.getElementById("div");

const distance = 1500;
const timeCount = 3000;

const intervalTime = 10;
let runCount = timeCount / intervalTime;
let moveValue = distance / runCount;

function handler() {
    let left = parseInt(divEle.style.left);
    if(left >= distance) {
        return;
    }
    divEle.style.left = left + moveValue;
    window.setTimeout(handler, intervalTime);
}

window.setTimeout(handler, intervalTime);
</script>

以上代码通过setTimeout每10毫秒为间隔时间改变一次元素的位置以实现元素的动画效果, 当然, 可以通过改变这个间隔时间来微调动画效果,可是你永远没有办法确定最优方案,因为它总会和刷新频率存在交叉。

通过requestAnimationFrame我们可以给出更好的解决方案

<div id="div" style="width:100px; height:100px; background-color:#000; position: absolute;left:0; top:0;">
    
</div>

<script type="text/javascript">

let divEle = document.getElementById("div");

const distance = 1500;
const timeCount = 3000;

function handler( time ) {
    if(time > timeCount) {
        time = timeCount;
    }
    divEle.style.left = time * distance / timeCount;  
    window.requestAnimationFrame( handler );
}

 window.requestAnimationFrame( handler );
</script>

如果setTimeout,handler函数也会被递归的重复调用,只是它的调用和显示的刷新频率是一致的,因此动画效果更加顺滑自然,也能找到性能和效果的最佳均衡点,得到最有的解决方案。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 现在我们,都很焦虑。同样用了一万小时去练习的我们,为什么好像,并不能取得长足的发展和进步? 为什么在职场打...
    无涯的生活日志阅读 115评论 6 5
  • 运营人需要具备哪些能力? 什么是运营?是做广告?泡论坛?做活动?写文案?还是运营微信群、搞线下沙龙?似乎这些都是...
    蓝蓝Lan阅读 223评论 0 0
  • 一缕晨光照尘刹 万簇山花遍山涯
    菩提果zk张珂阅读 269评论 0 1