步骤
- 继续 REPL: https://codesandbox.io/s/css-sidebar-animation-100-transform-wxchf?file=/App.svelte
- 点击"切换侧边栏"按钮
- 动画流畅,流畅
- 取消注释第 28 行
- 评论行 29
- 再次单击按钮
- 调用
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);
}
您可以注意到使用 % 原因:
动画运行
- 控制台.log 1
- 动画停止
- 控制台.log 2
- 动画运行
使用 px:
- 控制台.log 1
- 动画仍在运行
- 控制台.log 2
- 动画结束