如何用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
相关产品推荐
相关产品推荐

