我目前正在开发一个 Web 应用程序,我需要平滑地更新元素的位置,最好利用
requestAnimationFrame
来实现流畅的动画。但是,我在当前的实施中遇到了重大的性能问题,我希望获得一些有关如何优化它的见解或建议。
以下是我尝试过的两种更新元素位置的方法的简要概述:
直接样式操作:
requestAnimationFrame(() => (this.style.left = this.left + "px"));
使用该方法,性能优良,动画流畅。 根据性能监控,重新计算风格每帧耗时 0.39ms。
通过 CSS 变量更新:
requestAnimationFrame(
this._updatePosition("--vi-frame-left", this.left, COL_WIDTH)
);
// ...
private _updatePosition(cssVar, actualPosition, unitSize) {
const pos = this._isManagedByGrid
? actualPosition * unitSize + "px"
: actualPosition + "px";
this.style.setProperty(cssVar, pos);
}
在这种方法中,我使用 CSS 变量 (
--vi-frame-left
) 来控制位置。 _updatePosition
方法计算位置并相应地更新 CSS 变量。然而,这种方法会导致渲染速度明显变慢并且动画体验不稳定。
根据性能监控,重新计算风格每帧需要 36ms。
我怀疑性能下降是由于通过 CSS 变量间接操纵元素的位置,但我不完全确定。这是我的问题:
left
样式和通过 CSS 变量更新位置会有如此明显的性能差异?requestAnimationFrame
内的函数调用会显着提高性能吗?您在直接设置左侧样式和通过 CSS 变量更新位置之间遇到的明显性能差异可能是由于以下几个原因造成的:
渲染过程:直接设置style left属性,直接通过JavaScript操作元素的样式。然而,当使用CSS变量时,它涉及渲染管道中的额外步骤。更新 CSS 变量会触发样式重新计算和布局过程,这可能会导致您观察到的性能下降。
浏览器优化:不同的浏览器对某些操作的处理方式不同。某些浏览器可能比通过 CSS 变量更新更有效地优化直接样式操作,从而导致性能差异。
关于动画中 CSS 变量或频繁更新的已知性能问题:
CSS 变量更新:CSS 变量的频繁更新,尤其是在像 requestAnimationFrame 这样的高频函数中,可能会影响性能。当变量发生变化时,浏览器需要重新计算样式,过于频繁地执行此操作可能会导致性能下降。 优化CSS变量的方法:
减少更新:最小化 requestAnimationFrame 循环中 CSS 变量的更新频率。不要为位置的每个微小变化更新变量,而是批量更新或以更大的间隔更新。
避免不必要的重新计算:尽量避免 requestAnimationFrame 循环内不必要的计算。尽可能在循环外预先计算值,以减少动画期间的计算开销。
考虑替代方法:如果 CSS 变量方法仍然无法达到所需的性能,请考虑使用替代方法,例如使用 CSS 变换(平移、旋转等)来变换元素,以获得更流畅的动画。 CSS 转换通常是硬件加速的,并且比频繁的样式操作执行得更好。
浏览器测试和分析:跨不同浏览器测试您的应用程序并使用性能分析工具来识别瓶颈。这将有助于查明最需要优化的地方。
总而言之,通过降低 CSS 变量的更新频率并最大限度地减少动画循环中的计算开销来优化 CSS 变量的使用,有助于提高性能。但是,根据应用程序的复杂性和特定的浏览器行为,使用 CSS 转换等其他方法可能会产生更好的平滑动画性能。