You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让CSS @keyframes动画在指定关键帧处停止?

解决方案:无需重写动画,高效实现进度条停在指定百分比

不用非得用JS重写整个动画,有几个更高效的方案可以实现需求:


方案1:利用animation-delay负值直接跳转到目标进度

原动画总时长为5s,假设后端返回的目标进度为targetPercent(如30%),对应的时间点为5s * (targetPercent / 100)。给动画设置负的该延迟值,浏览器会直接从对应时间点的状态开始播放,配合forwards属性即可停在目标位置。

同时,原动画的颜色是随进度线性变化的,我们可以用CSS变量结合HSL颜色动态计算,摆脱预定义关键帧的限制:

修改后的CSS

.color-container {
  width: 100%;
  height: 200px;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  position: relative;
  width: 50%;
  border-radius: 4px;
  box-sizing: border-box;
  background: #fff;
  box-shadow: 0 10px 20px rgba(0, 0, 0, .5);
}

.Loading {
  position: relative;
  display: inline-block;
  width: 100%;
  height: 10px;
  background: #f1f1f1;
  box-shadow: inset 0 0 5px rgba(0, 0, 0, .2);
  border-radius: 4px;
  overflow: hidden;
}

.Loading:after {
  content: '';
  position: absolute;
  left: 0;
  width: 0;
  height: 100%;
  border-radius: 4px;
  box-shadow: 0 0 5px rgba(0, 0, 0, .2);
  /* 用CSS变量动态计算颜色:从绿色到黄色的色相渐变 */
  background: hsl(calc(80 - (var(--target-percent) * 0.2)), 80%, 50%);
  animation: load 5s forwards;
}

@keyframes load {
  0% { width: 0%; }
  100% { width: 100%; }
}

JS控制代码

const targetPercent = 30; // 替换为后端返回的百分比
const loadingBar = document.querySelector('.Loading:after');
// 计算负延迟值
const delay = `-${5 * (targetPercent / 100)}s`;

// 设置CSS变量和动画延迟
document.documentElement.style.setProperty('--target-percent', targetPercent);
loadingBar.style.animationDelay = delay;

方案2:用transition替代@keyframes,直接控制最终状态

如果不需要原动画的逐帧颜色细节(或可通过动态计算实现),用过渡效果更简洁,完全不需要预定义关键帧:

修改后的CSS

.color-container {
  width: 100%;
  height: 200px;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  position: relative;
  width: 50%;
  border-radius: 4px;
  box-sizing: border-box;
  background: #fff;
  box-shadow: 0 10px 20px rgba(0, 0, 0, .5);
}

.Loading {
  position: relative;
  display: inline-block;
  width: 100%;
  height: 10px;
  background: #f1f1f1;
  box-shadow: inset 0 0 5px rgba(0, 0, 0, .2);
  border-radius: 4px;
  overflow: hidden;
}

.Loading:after {
  content: '';
  position: absolute;
  left: 0;
  width: 0;
  height: 100%;
  border-radius: 4px;
  box-shadow: 0 0 5px rgba(0, 0, 0, .2);
  background: hsl(calc(80 - (var(--target-percent) * 0.2)), 80%, 50%);
  /* 过渡效果模拟原动画时长 */
  transition: width 5s ease;
}

JS控制代码

const targetPercent = 30; // 替换为后端返回的百分比
document.documentElement.style.setProperty('--target-percent', targetPercent);
const loadingBar = document.querySelector('.Loading:after');
// 直接设置目标宽度
loadingBar.style.width = `${targetPercent}%`;

方案3:动态暂停动画(保留原逐帧颜色)

如果需要严格保留原动画的逐帧颜色变化,可以先启动动画,计算到目标进度的时间后暂停:

JS控制代码

const targetPercent = 30; // 替换为后端返回的百分比
const totalDuration = 5000; // 原动画总时长,单位毫秒
const loadingBar = document.querySelector('.Loading:after');

// 启动动画
loadingBar.style.animationPlayState = 'running';
// 计算到目标进度的时间,到时暂停
setTimeout(() => {
  loadingBar.style.animationPlayState = 'paused';
}, totalDuration * (targetPercent / 100));

总结:无需每次生成新的@keyframes文件,上述方案都能高效实现根据后端数据停在指定进度,其中方案1和方案2的灵活性、性能表现更优。

内容的提问来源于stack exchange,提问作者ufghd34

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:09:52