说说requestAnimationFrame

首先从字面意思来看,就是请求动画帧(后面用raf代替)。
说起动画,css3的transition和animation,js的setTimeout和setInterval,jquery的animate()都可以做动画,这几种方式的性能和效率也有不同。今天聊的这个也可以做动画。

是什么

说白了就是做帧动画用的,所谓的请求动画帧,是告诉浏览器在下一次屏幕刷新的时候,别忘了运行raf这个方法,这一块要注意一点:每次屏幕刷新的时候,都会运行raf。也就是raf的运行频率是根据屏幕刷新频率来决定的。

性能怎么样

首先聊聊setTimeout。
setTimeout 其实就是通过设置一个间隔时间来不断的改变图像的位置,从而达到动画效果的。但我们会发现,利用seTimeout实现的动画在某些低端机上会出现卡顿、抖动的现象。 这种现象的产生有两个原因:

1.setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,实际上只是指定了把动画代码添加到浏览器UI线程等待执行的时间,如果队列前面有其他任务,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。
2.刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。
以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致,从而引起丢帧现象。 那为什么步调不一致就会引起丢帧呢?

首先要明白,setTimeout的执行只是在内存中对图像属性进行改变,这个变化必须要等到屏幕下次刷新时才会被更新到屏幕上。如果两者的步调不一致,就可能会导致中间某一帧的操作被跨越过去,而直接更新下一帧的图像。假设屏幕每隔16.7ms刷新一次,而setTimeout每隔10ms设置图像向左移动1px, 就会出现如下绘制过程:

第0ms: 屏幕未刷新,等待中,setTimeout也未执行,等待中;
第10ms: 屏幕未刷新,等待中,setTimeout开始执行并设置图像属性left=1px;
第16.7ms: 屏幕开始刷新,屏幕上的图像向左移动了1px, setTimeout 未执行,继续等待中;
第20ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=2px;
第30ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=3px;
第33.4ms:屏幕开始刷新,屏幕上的图像向左移动了3px, setTimeout未执行,继续等待中;

从上面的绘制过程中可以看出,屏幕没有更新left=2px的那一帧画面,图像直接从1px的位置跳到了3px的的位置,这就是丢帧现象,这种现象就会引起动画卡顿。所以丢帧现象可以说是因为屏幕刷新频率和代码执行不对称导致的。

那如果屏幕刷新频率和代码执行对称的话,是不是就不会发生丢帧现象了??。raf的诞生就解决了这一点,上文已经说了,raf的执行频率是根据屏幕刷新频率来说的,有图像的变化就会刷新屏幕,刷新屏幕就会运行raf,这样就解决了丢帧的现象。

如何用

raf()会接收一个参数,这个参数是一个函数,函数的作用就是负责改变下一次重绘时dom的样式。

var i = 0;
function updateDom(){
  let box = document.getElementById('box');
  i+=10;
  box.style.width = 300 + i +'px';
  if(i<500){
      requestAnimationFrame(updateDom)
  }
}
requestAnimationFrame(updateDom)

到此,raf解决了动画什么时候开始和最佳循环循环间隔的问题,但是代码具体的在哪个时间执行吗,确是不知道的,只知道动画在屏幕刷新时候开始。不过,mozRequestAnimationFrame()传递的函数也会接收一个参数,是一个时间码(从1970年1月1日起至今的毫秒数),表示下一次重绘发生的实际时间。
如果想知道距离上一次重绘过去的时间,可以查询mozAnimationStartTime,不过这个属性知识Mozilla实现了。目前chrome和IE都没有此属性。这个值包含上一次重绘的时间码,用传入回调函数的时间码减去这个时间,就能计算出在屏幕上重绘下一簇变化之前要经过多少时间。

function draw(timestamp){
  var differ = timestamp - startTime;//differ确定下一次重绘时间与现在时间的差值
  startTime = timestamp;//把timestamp重写为这一次的绘制时间
  mozRequestAnimationFrame(draw);
}
var startTime = mozAnimationStartTime;
mozRequestAnimationFrame(draw)

chrome和IE10+都给出了带前缀的requestAnimationFrame方法实现,不过与Mozilla的版本还是有点差异。
差异1:不回给回调函数传时间码。
差异2:chrome增加了第二个可选的参数:即将要发生变化的DOM元素。
chrome提供了一个取消帧动画的方法,webkitCancelAnimationFrame(),用于取消之前计划的重绘操作。
当然,作为一个新兴的API,兼容性问题肯定少不了。所以实际开发过程中,请注意兼容性的处理。

requestAnimationFrame的优点:
1.多个raf可以并行绘制。(这一点跟setTimeout和setInterval进入异步队列有关系。)
2.在隐藏或者不可见的元素汇总,raf将不会进行重绘和回流,这就意味着更少的CPU和GPU以及内存使用量。

  1. 由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态的话,动画就会暂停,节省了CPU开销。(对于这一点,本人试了试setTimeout和setInterval,发现用这两者做的动画在不激活的状态下也会暂停,不知道是chrome浏览器做了优化还是说只有chrome是这样。)

4.函数节流: 在高频率时间中(resize,scroll等),为了防止在一个刷新间隔内发生多次函数执行,使用raf可保证每个刷新间隔内,函数只能被执行一次,这样既能保证流浪性,也能更好的节省函数执行的开销。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容