javascript - JS — FLIP 技术和 requestAnimationFrame,重构为不嵌套

标签 javascript promise requestanimationframe

我在理解 requestAnimationFrame API 时遇到了一些困难。我认为它使浏览器等待回调完成,直到浏览器触发重绘(或回流?)。那是对的吗?如果在回调中调用requestAnimationFrame,浏览器将重新绘制并执行新的RAF的回调,然后再次重新绘制?如果是这种情况,我怎样才能使这个 API 的两个顺序调用更加异步/ promise 化,而不是像下面的示例那样嵌套它们?

这里我使用了 FLIP 技术将文档片段插入到 DOM 中并为 DOM 元素的高度设置动画,看起来效果很好。我不喜欢代码的回调性质/嵌套。我很难理解如何使其更加异步。是否可以使用 Promise 并使其可用?

window.requestAnimationFrame(() => {

    this.appendChild(frag);
    this.style.height = `${rows * rowHeight}px`;

    const { top: after } = this.getBoundingClientRect();

    this.style.setProps({
        "transform"  : `translateY(${before - after}px)`,
        "transition" : "transform 0s"
    });

    window.requestAnimationFrame(() => {
        this.style.setProps({
            "transform"  : "",
            "transition" : "transform .5s ease-out"
        });

    });

});

那么,我对英国皇家空军的先入之见是否正确?上面的代码示例如何没有回调并且不嵌套?

最佳答案

我不确定你自己对 requestAnimationFrame 的解释,但简单地说,它只是一个 setTimeout(fn, the_time_until_painting_frame)

简单地说,它将 fn 放入回调列表中,当下一个绘画事件循环发生时,这些回调将全部执行。这个绘画事件循环是一种特殊的事件循环,浏览器将在其中调用自己的绘画操作(CSS动画,WebAnimations等)。他们将每n次标记一个事件循环作为这样的绘画帧。这通常与屏幕刷新率同步。

因此,我们的 rAF 回调将在此事件循环中执行,就在浏览器执行其绘制操作之前。

<小时/>

现在,您偶然发现浏览器如何计算 CSS 转换:它们采用元素的当前计算值。
但是这些计算值不会同步更新。浏览器通常会等待这一绘画帧以便进行重新计算,因为要计算一个元素,您需要重新计算所有CSSOM树。

幸运的是,有一些 DOM 方法会同步触发此类回流,因为它们确实需要更新的框值,例如 Element.offsetTop getter。
因此,在设置初始样式(包括过渡样式)后,只需调用这些方法之一,您就可以同步触发过渡:

_this.style.height = "50px";


_this.style.setProperty("transform", "translateY(140px)");
_this.style.setProperty("transition", "transform 0s");

_this.offsetTop; // trigger reflow

_this.style.setProperty("transform", "");
_this.style.setProperty("transition", "transform .5s ease-out");
#_this {
  background: red;
  width: 50px;
}
<div id="_this"></div>

关于javascript - JS — FLIP 技术和 requestAnimationFrame,重构为不嵌套,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55137979/

相关文章:

javascript - 在 requestAnimationFrame 中每隔 x 秒调用一个函数

javascript - 同时应用两个不同的 CSS 转换

javascript - requestAnimationFrame 的触发频率远高于 60 fps

javascript - Strophe 注册插件

javascript - Javascript 是如何试图解释这个非法语句的?

angularjs - 有没有办法阻止 angular.service 注入(inject),直到加载服务的异步数据

javascript - jquery订阅函数返回错误

javascript - 将带有 Promise 的对象文字传递给 Q.all()

javascript - 有没有办法在使用 CommonJS 模块和 require 时包含一个目录?

Javascript 正则表达式包含