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

如何用单个动画实现多个Bootstrap进度条宽度动画并适配视口触发

解决方案

两个需求都可实现,具体优化方案如下:

核心优化点

  • 利用CSS自定义属性实现单组@keyframes适配所有不同宽度的进度条,无需重复定义多组动画
  • 修复原JS中类名拼写错误,批量监听所有进度条容器,动态读取每个进度条的目标宽度适配多实例

改造后HTML

给每个进度条添加data-progress属性存储目标百分比,无需单独定义bar1~bar5类:

<div class="col-sm-6">
  <h3 class="progress-title">SEO / SEM</h3>
  <div class="progress">
    <div class="progress-bar" data-progress="60">
      <div class="progress-value">60%</div>
    </div>
  </div>
</div>
<!-- 其余4个进度条仅需修改data-progress属性值和显示的百分比文本即可 -->

改造后CSS

仅保留1组通用动画,通过CSS变量动态适配不同宽度:

/* 通用动画触发类 */
.progress-bar.animated {
  animation: progressAnimate 3s ease-in-out;
  animation-fill-mode: both;
}
/* 全局唯一动画关键帧 */
@keyframes progressAnimate {
  0% { width: 0; }
  100% { width: calc(var(--target-width) * 1%); }
}

改造后JS

批量监听所有进度条容器,动态注入宽度变量:

const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    const progressBar = entry.target.querySelector('.progress-bar');
    // 读取当前进度条的目标宽度
    const targetWidth = progressBar.dataset.progress;
    // 注入CSS变量
    progressBar.style.setProperty('--target-width', targetWidth);

    if (entry.isIntersecting) {
      progressBar.classList.add('animated');
      return;
    }
    // 如果不需要离开视口重置进度,可删除下面这行代码
    progressBar.classList.remove('animated');
  });
});

// 批量注册所有进度条容器到监听器
document.querySelectorAll('.progress').forEach(progress => {
  observer.observe(progress);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:09:01