环形进度条动画在谷歌Chrome失效,其他浏览器正常运行
环形进度条Chrome浏览器失效问题解决建议
问题描述
开发了一个进入视口时触发的环形进度条动画,该效果在除Google Chrome外的所有浏览器中都能正常工作,但在Chrome中无法运行,怀疑问题与JavaScript代码相关,寻求解决建议。
问题分析
从提供的代码来看,Chrome失效的核心原因集中在以下几点:
- CSS中渐变ID与HTML不匹配,导致渐变样式无法加载
- 针对webkit的专属媒体查询覆盖了标准过渡属性,干扰动画执行逻辑
- IntersectionObserver的阈值设置过高,可能导致元素进入视口时无法及时触发
- Chrome对SVG属性过渡的缓存机制影响了重置状态后的二次触发
解决步骤
修复渐变ID引用错误
CSS中.circle-progress-value的stroke属性使用了url(#circle-gradient-%id%),但HTML中渐变ID为circle-gradient,删除%id%占位符,保证样式引用正确。移除webkit专属媒体查询块
现代Chrome已完全支持标准CSS过渡属性,该媒体查询块会覆盖标准过渡规则,直接删除即可恢复正常过渡逻辑。降低IntersectionObserver触发阈值
将阈值从0.5调整为0.1,确保元素刚进入视口边缘时就能触发动画,避免因元素尺寸或布局问题导致触发延迟。优化动画重置逻辑
当元素离开视口重置状态时,先临时移除过渡属性,设置初始值后再重新添加过渡,规避Chrome的过渡缓存影响下次触发。
修正后的完整代码
JavaScript
document.addEventListener('DOMContentLoaded', () => { const circleProgressBar = document.querySelector('.circle-progress-value'); const circleProgressNumber = document.querySelector('.circle-progress-number'); const checkmarkContainer = document.querySelector('.checkmark-container'); const countUp = (start, end, element, duration) => { let current = start; const stepTime = Math.abs(Math.floor(duration / (end - start))); const timer = setInterval(() => { if (current <= end) { element.textContent = current++; } else { clearInterval(timer); } }, stepTime); }; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { circleProgressBar.style.transition = 'stroke-dashoffset 2000ms'; circleProgressBar.style.strokeDashoffset = '0'; countUp(0, 50, circleProgressNumber, 2000); setTimeout(() => { checkmarkContainer.style.opacity = '1'; }, 2000); } else { // 重置时先移除过渡,避免缓存干扰 circleProgressBar.style.transition = 'none'; circleProgressBar.style.strokeDashoffset = '283'; circleProgressNumber.textContent = '0'; checkmarkContainer.style.opacity = '0'; // 延迟恢复过渡,确保下次触发正常 setTimeout(() => { circleProgressBar.style.transition = 'stroke-dashoffset 2000ms'; }, 10); } }); }, { threshold: 0.1 }); observer.observe(circleProgressBar); });
CSS
.circle-progress-container { position: relative; display: inline-block; width: 100%; padding-bottom: 100%; overflow: visible; } .bar-container { width: 400px; } .circle-progress { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: rotate(-90deg); } .circle-progress-bg, .circle-progress-value { stroke-linecap: round; } .circle-progress-bg { stroke: lightgray; } .circle-progress-value { stroke: url(#circle-gradient); stroke-dasharray: 283; stroke-dashoffset: 283; transition: stroke-dashoffset 2s; transition-property: stroke-dashoffset; } .circle-progress-text { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; text-align: center; } .circle-progress-number-container { display: flex; align-items: baseline; } .circle-progress-number { transition: 2s; } .circle-progress-label { font-size: 12px; font-weight: normal; margin-top: -10px; } .checkmark-container { position: absolute; top: -2px; left: 50%; transform: translateX(-50%); opacity: 0; transition: opacity 0.5s, transform 0.5s; } .checkmark-circle { position: relative; width: calc(16px + 5px); height: calc(16px + 5px); background-color: white; border-radius: 50%; box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); } .checkmark { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); stroke: deepskyblue; stroke-linecap: round; }
HTML
<div class="bar-container"> <div class="circle-progress-container"> <svg class="circle-progress" viewBox="0 0 100 100"> <defs> <linearGradient id="circle-gradient" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:red"/> <stop offset="100%" style="stop-color:blue"/> </linearGradient> </defs> <circle class="circle-progress-bg" cx="50" cy="50" r="45" stroke-width="1" fill="none" /> <circle class="circle-progress-value" cx="50" cy="50" r="45" stroke-width="1" fill="none" /> </svg> <div class="circle-progress-text"> <div class="circle-progress-number-container" style="font-size: 40px;"> <span class="circle-progress-number">50</span><span>+</span> </div> <div class="circle-progress-label" style="font-size: 14px;">Projects</div> </div> <div class="checkmark-container"> <div class="checkmark-circle"> <svg class="checkmark" width="16px" height="16px" viewBox="0 0 20 20"> <polyline points="6,10 9,13 14,8" stroke-width="2" fill="none" /> </svg> </div> </div> </div> </div>
内容的提问来源于stack exchange,提问作者Holaloro
相关产品推荐
相关产品推荐

