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

如何用CSS和JavaScript实现多类元素的视图触发多关键帧动画?

解决技能区域条形进度条与圆形动画同步触发问题

问题出在哪?

大概率是你的IntersectionObserver只监听了圆形动画的单个元素,没覆盖到整个技能区域;或者条形进度条的动画触发逻辑(比如CSS类的添加)没和Observer的回调关联上,导致只有圆形动起来。

直接上手改

1. 让Observer盯整个技能区域

别单独盯圆形元素,直接监听包含所有条形和圆形的父容器(比如叫.skills-section),只要这个区域滚进视图,一次性触发所有子元素的动画。

2. 调整CSS动画触发方式

给条形和圆形都设好初始状态,然后用同一个激活类(比如animate-skills)来触发动画,这样就能同步动:

/* 条形进度条初始状态:宽度为0 */
.line-bar {
  width: 0;
  height: 8px;
  background: #2c3e50;
}

/* 圆形进度条初始状态:隐藏进度,透明度为0 */
.circle-progress {
  stroke-dasharray: 283;
  stroke-dashoffset: 283;
  opacity: 0;
}

/* 激活类触发所有动画 */
.skills-section.animate-skills .line-bar {
  animation: bar 1.5s ease forwards;
}

.skills-section.animate-skills .circle-progress {
  animation: circle_animation 1.5s ease forwards;
  opacity: 1;
}

/* 保留你的关键帧动画 */
@keyframes bar {
  to {
    width: var(--progress-width); /* 用CSS变量控制每个条形的最终宽度 */
  }
}

@keyframes circle_animation {
  to {
    stroke-dashoffset: var(--dash-offset); /* 用CSS变量控制圆形进度 */
  }
}

3. 修改JavaScript代码

让Observer监听技能区域容器,进入视图就加激活类,想只触发一次就取消观察,想重复触发就不加unobserve:

const skillsSection = document.querySelector('.skills-section');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      skillsSection.classList.add('animate-skills');
      // 只触发一次就加这句,想重复触发就删掉
      observer.unobserve(entry.target);
    }
    // 可选:离开视图时移除类,再次滚动回来重新触发
    // else {
    //   skillsSection.classList.remove('animate-skills');
    // }
  });
}, {
  threshold: 0.1, // 区域10%进入视图就触发
  rootMargin: '0 0 -50px 0' // 微调触发时机,避免过早或过晚
});

observer.observe(skillsSection);

4. HTML配合加CSS变量

给每个条形和圆形加对应的变量控制最终进度:

<div class="skills-section">
  <!-- 条形进度条示例 -->
  <div class="skill-item">
    <span>HTML</span>
    <div class="line-bar" style="--progress-width: 95%;"></div>
  </div>

  <!-- 圆形进度条示例 -->
  <div class="circle-skill">
    <svg class="circle-progress" style="--dash-offset: 14;" viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="45" fill="none" stroke-width="10" stroke="#ecf0f1"/>
      <circle cx="50" cy="50" r="45" fill="none" stroke-width="10" stroke="#2980b9"/>
    </svg>
    <span>95%</span>
  </div>
</div>

踩坑提醒

  • 检查CSS选择器优先级,别让初始状态被其他样式覆盖了。
  • 确保所有要动画的元素都在.skills-section里面,不然激活类的样式找不到它们。
  • 如果还是没效果,打开浏览器控制台看看Observer有没有正常监听,元素类有没有加上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:32:01