hushicai / hushicai.github.io

Blog
https://hushicai.github.io
27 stars 1 forks source link

requestAnimationFrame回调时机 #49

Open hushicai opened 5 years ago

hushicai commented 5 years ago

按照Event Loop标准文档,requestAnimationFrame是在Update the rendering阶段中执行的:

image

它在一帧中的位置应该是:

image

requestAnimationFrame会在style/layout/paint之前触发:

If v-sync: 
  render-synced events 
  raf callbacks
  layout + paint 
handle task

但所有浏览器都是这样吗?并不是。。。

jakearchibald早在两年前就提出了这个问题

他提出,Chrome、Firefox等会在style/layout/paint之前触发回调,而IE、Edge、Safari则是在style/layout/paint之后触发:

According to event-loop-processing-model, any queued requestAnimationFrame callbacks should be executed before the next recalc/layout/paint. Safari seems to execute them afterwards.

他写了一个例子来演示这个问题:

test.style.transform = 'translate(0, 0)';

document.querySelector('button').addEventListener('click', () => {
  const test = document.querySelector('.test');
  test.style.transform = 'translate(400px, 0)';

  requestAnimationFrame(() => {
    test.style.transition = 'transform 3s linear';
    test.style.transform = 'translate(200px, 0)';
  });
});

在不同浏览器上,表现是不一样的:

chrome (chrome)

safari (safari)

chrome、firefox是向右移动,而Edge、IE、Safari是向左移动。

从上面的例子中可以看出,chrome是符合标准的,它会尽可能快地在下次render之前触发回调(大部分情况是在当前帧中完成的),但Safari的做法看起来则像是把回调推迟到下一帧。

jakearchibald之前还在twitter上发起了投票,60%的人都认为应该是在render之后,但标准是render之前的…

这就有点尴尬了

jakearchibald认为这很让人迷惑,随后分别给EdgeSafari提了bug。

Edge的响应比较及时,Edge 18以上版本已经修复;而Safari目前还在跟进中。

hushicai commented 5 years ago

whatwg/html#2569

liximomo commented 3 years ago

事实上现在 chrome 也是像左移动。

hushicai commented 3 years ago

@liximomo 知乎上有更详细的文章,可以去看看。https://zhuanlan.zhihu.com/p/64917985