首页 > 解决方案 > 如果我使用 translateX(100%),在繁重的 javascript 函数期间,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);
  }
}

标签: javascriptcsscss-animationscss-transitionssvelte

解决方案


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

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

  • 主线程
  • 合成器线程

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

通常,主线程负责:

  • 运行你的 JavaScript。

  • 计算 HTML 元素的 CSS 样式。

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

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

通常,合成器线程负责:

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

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

  • 确定页面的哪些部分是可见的。确定滚动时哪些部分很快可见。

  • 滚动时移动页面的某些部分。

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

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

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

如果任何动画触发了绘制、布局或两者,则需要“主线程”来完成工作。这对于基于 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. 控制台日志 1
  2. 动画停止
  3. 控制台日志 2
  4. 动画运行

使用像素:

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

推荐阅读