【问题标题】:How to achieve smooth CSS animation on CSS width change?如何在 CSS 宽度变化时实现平滑的 CSS 动画?
【发布时间】:2019-08-18 20:57:19
【问题描述】:
我正在制作自己的进度条,该进度条将在 5 分钟到 1 秒的不同时间段内填满。我的想法是:
- 我有一个栏,每 x 秒将 CSS 宽度设置为 0%
- 然后我使用 JS 将条形宽度增加 1%。
它的工作原理是这样的:https://jsfiddle.net/dnh4y39c/
这种方法存在一些问题:
动画仅在 https://jsfiddle.net/dnh4y39c/1/,
我可以用 CSS 过渡来解决这个问题,但它完全崩溃了
时机,如果我在栏上设置transition: all 0.5s;,那么它可以工作
相当长的时间,但它完全打破了更快
负载,例如。进度条应该在 1 秒内完成,但它会停止
持续 0.5 秒,然后一次性设置 100% 的动画,请参阅:
https://jsfiddle.net/dnh4y39c/1/
我想知道是否应该调整宽度或者只是移动到画布?我不知道画布那么好,但我想它可能性能更高并且占用的资源更少?我的应用程序中可能有多个进度条,因为我需要单独加载所有模块(所以没有一个简单的加载器,但在某些地方甚至可能超过 50 个 - 我知道,这很疯狂,但我只是在关注文档)。
感谢您的任何意见:)
【问题讨论】:
标签:
javascript
css
animation
progress-bar
width
【解决方案1】:
需要考虑的几件事是:
- 避免使用
setInterval(),如果间隔回调需要更长的时间来执行它本身的间隔持续时间,它会产生“跳跃”的动画行为。如果需要帧间延迟,请改用setTimeout()
- 考虑使用
window.requestAnimationFrame() 来更新进度条的动画。使用window.requestAnimationFrame() 可确保您的进度条更新与浏览器重绘/重绘周期同步
包含这两个想法的代码的更新版本可能如下所示:
function interation(element, iterationDuration, i) {
window.requestAnimationFrame(function() {
/*
Update the width and transition duration of the element for this iteration
*/
element.style.width = `${i}%`;
element.style.transitionDuration = `${iterationDuration}ms`;
/*
Increment/calculate next percentage value for progress bar
*/
const next = (i === undefined ? 0 : i) + 1;
if (next <= 100) {
/*
Pass element, timeout, and next value through as arguments
to next interation() call
*/
setTimeout(interation, iterationDuration, element, iterationDuration, next);
}
})
}
interation(document.querySelector(".progress__bar"), 20);
// interation(document.querySelector(".progress__bar"), 2000); Long interval
// interation(document.querySelector(".progress__bar"), 20); Short interval
* {
box-sizing: border-box;
}
.progress__bar {
transition: width linear;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-radius: 4px;
background: #f00;
}
<div class="item">
<div class="item__progress">
<div class="progress__bar" style="width: 0%;"></div>
</div>
</div>