JS - FLIP技术和requestAnimationFrame,重构不能嵌套

问题描述 投票:0回答:1

我在理解requestAnimationFrame API时遇到了一些麻烦。我认为这会让浏览器等待回调完成,直到浏览器触发重绘(或重排?)。那是对的吗?如果你在回调中调用requestAnimationFrame,浏览器将重新绘制并执行新的RAF的回调,然后重新重新绘制?如果是这种情况,我怎么能对这个API进行两次顺序调用更多的是异步/ promisified,而不是像下面的例子那样嵌套它们?

在这里,我使用FLIP技术将文档片段插入DOM并为DOM元素的高度设置动画,它似乎工作正常。我不喜欢代码的回调性质/嵌套。我很难理解如何让它更加异步。是否可以使用承诺并使其成为可能的?

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"
        });

    });

});

那么,我对RAF的先入为主的观念是否正确?以上代码示例如何能够没有回调而不是嵌套?

javascript promise requestanimationframe
1个回答
1
投票

我不确定自己对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>
© www.soinside.com 2019 - 2024. All rights reserved.