JS基于data属性修改SVG stroke-dashoffset并保留圆环动画
问题原因
代码不生效是三个核心错误导致的:
- 定时器清除参数传错:
clearInterval需要传入定时器ID,你传的是计数变量counters[index](数值类型),定时器永远不会被清除,会持续异常运行。 - 偏移量计算逻辑错误:一是
parseInt位置错误,number.dataset.num / 100本身是小数,直接转整数会丢失精度;二是你每次都用最终的data-num值计算偏移,没有和当前递增的计数器绑定,无法实现和数字同步的动画效果。 - CSS动画优先级冲突:你给
circle写死了anim动画,所有圆环动画终态都固定为stroke-dashoffset:70,CSS动画运行时的属性优先级会覆盖JS设置的内联样式,导致JS修改的值不生效。
修改方案
要保留数字递增+圆环进度同步的动画效果,按以下步骤调整:
- 删除CSS中写死终态的
anim动画相关代码,避免覆盖JS动态设置的偏移值 - 修正JS中定时器清除的传参,传入正确的定时器ID
- 调整偏移量计算公式,和当前递增的计数值绑定,实现进度同步增长
- 提前把
data-num的值转为数字,避免计算时的类型错误
修改后完整代码
JS部分
const numbers = document.querySelectorAll('.number'); const svgEl = document.querySelectorAll('svg circle'); const counters = Array(numbers.length).fill(0); const intervals = Array(numbers.length); numbers.forEach((number, index) => { // 提前拿到目标进度值,转成数字 const target = parseInt(number.dataset.num); intervals[index] = setInterval(() => { if(counters[index] === target){ // 传入正确的定时器ID清除任务 clearInterval(intervals[index]); }else{ counters[index] += 1; number.innerHTML = counters[index] + "%"; // 用当前计数值计算实时偏移,和数字进度完全同步 svgEl[index].style.strokeDashoffset = 472 * (1 - counters[index] / 100); } }, 20) })
CSS部分(仅需调整circle相关样式)
/* 其余样式保持不变,只修改circle选择器的内容 */ circle { fill: none; stroke: #f75023; stroke-width: 20px; stroke-dasharray: 472; stroke-dashoffset: 472; /* 删除原有的animation属性,移除写死的anim动画 */ } /* 完全删除原代码中@keyframes anim的整段动画定义 */
HTML部分
原有HTML不需要调整,JS运行时会自动覆盖.number里的初始文本,自动匹配data-num设置的目标值。
效果说明:页面加载后,数字会从0开始递增到
data-num设置的目标值,同时圆环进度会同步从0增长到对应百分比,动画节奏和原有20ms间隔的流畅度保持一致,三个圆环会分别匹配90%、50%、70%的进度显示。
内容的提问来源于stack exchange,提问作者Mohamad
相关产品推荐
相关产品推荐

