在繁重的javascript函数中,如果我使用translateX(100%),css动画就会停止



步骤

  1. 继续 REPL: https://codesandbox.io/s/css-sidebar-animation-100-transform-wxchf?file=/App.svelte
  2. 点击"切换侧边栏"按钮
  3. 动画流畅,流畅
  4. 取消注释第 28 行
  5. 评论行 29
  6. 再次单击按钮
  7. 调用heavy()函数时动画停止(在toggleSidebar()函数中(

问题

我不明白为什么会这样?

如果我将-200px更改为-100%发生了什么导致动画停止?

如何解决问题?如果我事先不知道侧边栏宽度怎么办?如果它是动态的呢?

法典

.sidebar {
animation: sidebar-slide-right 3s ease-out;
}
@keyframes sidebar-slide-right {
0% {
/* transform: translateX(-100%); */
transform: translateX(-200px);
}
100% {
transform: translateX(0);
}
}

我花了一些时间在 Web 浏览器开发工具中使用性能时间来测试您的 repl。我的结论是:

在现代网络浏览器中,我们有

  • 主线程
  • 合成器线程

第二个真的很好,因为通过自己承担一些责任来帮助主线程。

通常,主线程负责:

  • 运行你的 JavaScript。

  • 计算 HTML 元素的 CSS 样式。

  • 布局您的页面。将元素绘制成一个或多个位图。

  • 将这些位图移交给合成器线程。

通常,合成器线程负责:

  • 通过 GPU 将位图绘制到屏幕上。

  • 要求主线程更新页面中可见或即将可见部分的位图。

  • 确定页面的哪些部分是可见的。弄清楚哪个 滚动时,部分很快就会可见。

  • 滚动时移动页面的各个部分。

来源: http://sking7.github.io/articles/572118798.html

基于 CSS 的动画和本机支持的 Web 动画是 通常在称为"合成器线程"的线程上处理。这 不同于浏览器的"主线程",其中样式、布局、 绘画和JavaScript被执行。这意味着如果浏览器 正在主线程上运行一些昂贵的任务,这些动画 可以继续前进而不会被打断。

在许多情况下,对转换和不透明度的其他更改也可能是 由合成器线程处理。

如果任何动画触发绘画、布局或两者兼而有之,则"主线程" 将被要求做工作。对于 CSS 和 CSS 都是如此 基于 JavaScript 的动画,以及布局或绘制的开销将 可能使与CSS或JavaScript执行相关的任何工作相形见绌, 使问题变得毫无意义。

来源: https://developers.google.com/web/fundamentals/design-and-ux/animations/animations-and-performance

所以当我们不得不处理动画时,合成器非常好。使用 px 作为度量单位很容易,可以通过合成器线程完成,但使用 % 会使我们的浏览器计算动画的每个"步骤",因此主线程必须帮助我们完成它。通过使用await您可以阻止主线程,以便您的浏览器等待重新计算位置。使用绝对单位时,合成器线程会执行动画,因此即使您阻止了主线程,动画也能平稳运行。

将您的代码替换为

async function toggleSidebar() {
sidebarVisible = !sidebarVisible;
console.log("1");
await sleep(800);
console.log("2");
heavy(40);
}

您可以注意到使用 % 原因:

动画运行

  1. 控制台.log 1
  2. 动画停止
  3. 控制台.log 2
  4. 动画运行

使用 px:

  1. 控制台.log 1
  2. 动画仍在运行
  3. 控制台.log 2
  4. 动画结束

最新更新