如何使用JavaScript实现多组独立运行的环形进度条
修复多组环形进度条仅第一组生效的问题
你猜的没错,document.querySelectorAll返回的是节点列表(NodeList),直接访问它的innerText或style属性只会作用于列表里的第一个元素,加上所有进度条共用同一个定时器和计数器,导致只有第一组能正常动起来。
修复思路
给每个进度条单独创建动画逻辑,通过循环遍历节点列表,为每组进度条绑定独立的计数器、目标值和定时器:
- 用
forEach遍历节点列表,同时配对对应的进度条和数值元素 - 每组进度条维护自己的起始值、目标值和定时器
- 单独更新每组的文本内容和进度条样式
修复后的完整代码
HTML(无需修改)
<div class="container"> <div class="circular-progress"> <span class="progress-value">50</span> </div> <span class="text">HTML & CSS</span> </div> <div class="container"> <div class="circular-progress"> <span class="progress-value">67</span> </div> <span class="text">JavaScript</span> </div> <div class="container"> <div class="circular-progress"> <span class="progress-value">80</span> </div> <span class="text">React</span> </div>
CSS(仅新增间距优化,核心样式不变)
* { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body { height: 100vh; display: flex; align-items: center; justify-content: center; gap: 20px; /* 新增:避免进度条挤在一起 */ background: #7d2ae8; } .container { display: flex; width: 420px; padding: 50px 0; border-radius: 8px; background: #fff; row-gap: 30px; flex-direction: column; align-items: center; } .circular-progress { position: relative; height: 250px; width: 250px; border-radius: 50%; background: conic-gradient(#7d2ae8 3.6deg, #ededed 0deg); display: flex; align-items: center; justify-content: center; } .circular-progress::before { content: ""; position: absolute; height: 210px; width: 210px; border-radius: 50%; background-color: #fff; } .progress-value { position: relative; font-size: 40px; font-weight: 600; color: #7d2ae8; } .text { font-size: 30px; font-weight: 500; color: #606060; }
修改后的JavaScript
const circularProgressList = document.querySelectorAll(".circular-progress"); const progressValueList = document.querySelectorAll(".progress-value"); const speed = 10; // 遍历每组进度条,创建独立动画 circularProgressList.forEach((circularProgress, index) => { const progressValue = progressValueList[index]; let progressStartValue = 0; // 把文本转为数字作为目标值 const progressEndValue = parseInt(progressValue.innerText); const progress = setInterval(() => { progressStartValue++; // 更新当前组的数值文本 progressValue.textContent = `${progressStartValue}%`; // 更新当前组的进度条样式 circularProgress.style.background = `conic-gradient(#7d2ae8 ${progressStartValue * 3.6}deg, #ededed 0deg)`; if (progressStartValue === progressEndValue) { clearInterval(progress); } }, speed); });
关键修改点
- 用
forEach循环遍历所有进度条元素,确保每组都有独立的动画逻辑 - 每组进度条单独存储自己的起始值和目标值,避免互相干扰
- 操作DOM时,针对当前循环的元素(
circularProgress和progressValue)进行修改,而不是整个节点列表
内容的提问来源于stack exchange,提问作者rnkwill
相关产品推荐
相关产品推荐

