点击上方蓝字关注“小郑搞码事”,每天都能学到知识,搞懂一个问题!
CSS3 transition、requestAnimationFrame、setTimeout。都可以用来搞动画。今天,这里我来谈一下大家都推荐的动画处理方式:requestAnimationFrame。该方法通过在系统准备好绘制动画帧时调用该帧,从而为创建动画网页提供了一种更平滑高效的方法,在此API之前,使用setTimeout和setInterval绘制的动画并没有为Web开发人员提供有效的方法来规划动画的图形计时器,这导致了动画过度绘制,浪费CPU周期以及消耗额外的电能等问题。而且,即使看不到网站,特别是当网站使用背景选项卡中的页面或浏览器已最小化时,动画都会频繁出现。
一、先来分析一下动画不流畅的本质问题
如上图所示:
1、上一层箭头列表,是屏幕以16.7ms刷新一次。
2、下一层箭头列表,是程序以10ms请求向屏幕展示动画。
这里注意一个容易忽视的事实,就是:
1、屏幕在两次刷新间隔时,屏幕上的内容是不变的。
2、程序请求向屏幕展示图像时,当前屏幕不是立马展示的,而是在屏幕自己的下一次刷新时,才展示。
基于以上分析,在上图中,请求屏幕刷新这个动作,只会在上一层箭头的 第二个箭头处响应,同时在2号整个窗口内都是展示响应结果。
这个时候,下一层箭头列表里第三个请求展示屏幕来了,此时按事实1,内容不会变,因为还没到屏幕自己的刷新时间。接着,下一层箭头列表里第 四 个请求展示屏幕来了,此时,屏幕刷新也刚好到了。所以屏幕刷新只会展示最新来的 屏幕刷新请求。也就是第四个。而第三个,自然被忽略掉了。也就是请求帧不连续了,so 不流畅。
二、切入到重点方法requestAnimationFrame 方法
(在万维网联合会 (W3C) 的针对基于脚本的动画的计时控制规范中定义)可以解决丢失帧的问题,因为它使应用能够在浏览器需要更新页面显示时(而且仅在这种情况下)获得通知。 因此,应用可与浏览器的绘制时间间隔保持完全一致,并且仅使用适量的资源。从 setTimeout 切换到 requestAnimationFrame 非常容易,因为它们都规划单个回调。要实现持续的动画,请在调用动画函数后再次调用 requestAnimationFrame。
目前,各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。
三、接下来我举个例子
1、首先,上面提到的,封装一个兼容版本的requestAnimationFrame。
这个不难,比较简单,下面我以GIF的方式展示一下代码(当然,网上一搜,都有)。
2、应用requestAnimationFrame方法
DOM结构:
JS代码:
看一下运行效果吧
四、最后总结一下
requestAnimationFrame是js动画实现神器,但需要用好它,比如:有些场景下会出现一些一帧多调的情况。这需要具体问题具体去处理。