求助:实现滚动到视图时触发圆形进度条动画
实现滚动触发的无限循环圆形进度条动画(基于jQuery Circle Progress)
嘿,我来帮你搞定这个圆形进度条的问题!你想要实现滚动到可见区域才触发动画+动画无限循环,之前用waypoints和AOS没效果,咱们一步步来解决它~
问题分析
你现在的代码一页面加载就会直接播放所有进度条的动画,既没有绑定滚动触发逻辑,也没有循环动画的处理。咱们需要解决两个核心需求:
- 当进度条滚动到视口可见范围时,才启动动画
- 动画完成后自动重复,实现无限循环
完整解决方案代码
首先确保你已经正确引入了jQuery和circleProgress插件(如果还没引入,要先加在<head>或者</body>结束前)。
1. HTML结构(保留你的原有结构,无需大改)
<div class="card"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">HTML</div> </div> <div class="card css"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">CSS</div> </div> <div class="card js"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">Javascript</div> </div> <div class="card ps"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">Photoshop</div> </div> <div class="card pp"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">Premiere Pro</div> </div> <div class="card sql"> <div class="circle"> <div class="bar"></div> <div class="box"><span></span></div> </div> <div class="text">MySQL</div> </div>
2. CSS样式(让进度条和文字正确显示)
.card { display: inline-block; margin: 20px; text-align: center; } .circle { position: relative; width: 150px; height: 150px; } .circle .bar { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .circle .box { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24px; font-weight: bold; }
3. jQuery代码(实现滚动触发+无限循环)
// 统一管理每个技能的目标进度值 const skillValues = { default: 0.80, css: 0.80, js: 0.70, ps: 0.85, pp: 0.80, sql: 0.65 }; // circleProgress基础配置 const baseOptions = { startAngle: -1.55, size: 150, fill: { gradient: ['#a445b2', '#fa4299'] }, animation: { duration: 2000 } // 动画时长,可根据需求调整 }; // 判断元素是否在视口可见范围内的工具函数 function isInViewport(element) { const rect = element.getBoundingClientRect(); return ( rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.bottom >= 0 ); } // 单个进度条的动画循环逻辑 function animateCircle($bar, targetValue) { // 从0开始初始化进度条 $bar.circleProgress({ ...baseOptions, value: 0 }).on('circle-animation-progress', function(event, progress, stepValue) { // 更新进度百分比文字 $(this).parent().find("span").text(String(stepValue.toFixed(2).substr(2)) + "%"); }).on('circle-animation-end', function() { // 动画结束后延迟1秒重新启动循环(可调整延迟时间) setTimeout(() => { // 只有元素还在视口内才继续循环 if (isInViewport($bar[0])) { animateCircle($bar, targetValue); } }, 1000); }); // 启动动画到目标进度值 $bar.circleProgress('value', targetValue); } // 滚动监听事件:检测元素是否进入视口,触发对应动画 $(window).on('scroll', function() { $('.card').each(function() { const $card = $(this); const $bar = $card.find('.bar'); // 用data属性标记是否已启动动画,避免滚动时重复触发 if (!$card.data('animated') && isInViewport($card[0])) { $card.data('animated', true); // 获取当前技能的目标进度值 const skillClass = $card.attr('class').split(' ')[1]; const targetValue = skillValues[skillClass] || skillValues.default; animateCircle($bar, targetValue); } }); }); // 页面加载时主动触发一次滚动检测,避免元素一开始就在视口内不启动动画 $(window).trigger('scroll');
关键逻辑解释
- 视口检测:
isInViewport函数用来判断元素是否进入了用户可见区域,确保只有滚动到进度条时才启动动画。 - 无限循环:在
circle-animation-end事件中设置延迟,重新调用动画函数,同时会再次检查元素是否在视口内,避免元素滚出后仍继续动画。 - 防重复触发:用
data('animated')给每个卡片标记是否已启动动画,防止滚动时多次触发同一动画。 - 统一配置:把所有技能的进度值放在
skillValues对象里,方便后续修改和维护。
这样调整后,你就能实现滚动触发动画+无限循环的效果啦~如果需要调整动画速度或者循环间隔,修改animation.duration或者setTimeout的时间即可。
内容的提问来源于stack exchange,提问作者steveleeburner




