游乐游手机版
首页/前端开发/文章详情

如何使用 JavaScript 创建多个独立运行的环形进度条

时间:2026-04-25 21:52
如何为多个环形进度条绑定独立动画:告别“仅第一个生效”的陷阱 在开发仪表盘或数据看板时,我们常常需要同时渲染多个环形进度条,用来展示像技能掌握度、任务完成率这类指标。但一个常见的“坑”是:代码写完后,只有第一个进度条在动,后面的全都“躺平”了。这问题出在哪?根源往往在于DOM查询和状态管理的方式——

如何为多个环形进度条绑定独立动画:告别“仅第一个生效”的陷阱

在开发仪表盘或数据看板时,我们常常需要同时渲染多个环形进度条,用来展示像技能掌握度、任务完成率这类指标。但一个常见的“坑”是:代码写完后,只有第一个进度条在动,后面的全都“躺平”了。这问题出在哪?根源往往在于DOM查询和状态管理的方式——如果粗暴地一次性选中所有元素统一操作,变量和定时器就会互相打架,最终只有“胜出”的那个能正常执行。

那么,正确的思路是什么?核心在于作用域隔离。我们需要把每个进度条连同它的容器看作一个独立的模块,为每个模块单独管理其状态和动画逻辑。这样一来,无论页面上有多少个进度条,它们都能井水不犯河水,各自流畅运行。

✅ 正确实现步骤

要实现这种隔离,关键在于改变遍历的维度。别再直接去抓所有 .circular-progress 元素了,而是应该以容器为单位,逐个击破。

  1. 按容器遍历:首先,使用 document.querySelectorAll(‘.container’) 获取页面上所有的容器节点。这一步是建立独立作用域的基础。
  2. 作用域内查询:接着,在遍历每个容器时,只在这个容器的范围内查找它专属的 .circular-progress.progress-value 元素。这就确保了每个进度条操作的都是自己的DOM节点。
  3. 独立状态管理:为每一个进度条实例单独声明其状态变量,比如动画起始值、目标结束值以及动画速度。这些变量被封闭在各自的作用域里,自然不会互相覆盖。
  4. 独立定时器控制:最后,为每个进度条启动自己独立的 setInterval 计时器。当某个进度条动画完成时,只清除它自己的定时器,完全不会影响到其他正在运行的进度条。

按照这个思路,下面是一段完整、可直接运行的Ja vaScript实现代码:

const containers = document.querySelectorAll(‘.container’);
containers.forEach(container => {
  const circularProgress = container.querySelector(‘.circular-progress’);
  const progressValue = container.querySelector(‘.progress-value’);
  // 确保文本内容为数字(兼容空格或单位)
  const targetValue = parseInt(progressValue.textContent.trim(), 10) || 0;
  let progressStartValue = 0;
  const speed = 15; // 可按需调整动画速度
  const progress = setInterval(() => {
    progressStartValue++;
    // 更新显示数值(带 % 符号)
    progressValue.textContent = `${progressStartValue}%`;
    // 动态更新 conic-gradient 背景角度(360° ÷ 100 = 3.6°/1%)
    circularProgress.style.background = `conic-gradient(
      #7d2ae8 ${progressStartValue * 3.6}deg,
      #ededed 0deg
    )`;
    if (progressStartValue >= targetValue) {
      clearInterval(progress);
      // 可选:确保最终值精确显示(避免因四舍五入偏差)
      progressValue.textContent = `${targetValue}%`;
      circularProgress.style.background = `conic-gradient(
        #7d2ae8 ${targetValue * 3.6}deg,
        #ededed 0deg
      )`;
    }
  }, speed);
});

⚠️ 注意事项

掌握了核心方法,再注意几个细节,能让你的实现更加稳健和高效:

  • 避免 innerText 误读:原代码中直接在NodeList上使用 innerText 是无效的,务必先定位到单个具体元素再读取其文本内容。
  • 防止重复初始化:确保脚本在DOM内容加载完成后执行,最简单的方法是将代码包裹在 DOMContentLoaded 事件监听器中。
  • 性能优化建议:如果页面需要同时动画的进度条数量非常多(比如超过10个),可以考虑用 requestAnimationFrame 替代 setInterval。这能带来更流畅的动画效果和更好的电池续航表现。
  • 样式健壮性:为 .circular-progress 元素设置一个初始的 conic-gradient 背景样式,可以避免动画第一帧可能出现的闪烁问题。
  • 语义化增强:别忘了可访问性。为每个进度条添加 aria-valuenowaria-valuemax 属性,能极大帮助使用屏幕阅读器的用户理解当前进度。

采用这种“容器驱动、实例隔离”的设计模式,好处是显而易见的。你不仅能轻松管理任意数量的进度条,还能为每个进度条单独配置不同的颜色主题、动画速度甚至缓动函数。这实际上是将进度条封装成了一个高度模块化、可复用的UI组件,无论是维护还是扩展,都变得轻而易举。

立即学习“Ja va免费学习笔记(深入)”;

来源:https://www.php.cn/faq/2327896.html
上一篇CSS如何实现波浪形的颜色分割线_mask-image与SVG路径技术 下一篇CSS如何根据图片亮度自动调整文字色_Canvas亮度检测与CSS类切换
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
如何在JavaScript中实现基于旋转视野的FOV射线绘制详解
前端开发 · 2026-07-01

如何在JavaScript中实现基于旋转视野的FOV射线绘制详解

如果用一句话概括核心,那就是:在 RayCasting 游戏开发中,绘制动态视野边界线(FOV)最可靠的方式是在逻辑层通过数学公式将坐标“算”出来,而不是依赖 Canvas 绘图上下文的旋转操作。 在实现类似 Doom 风格的 RayCasting 游戏时,动态视野(Field of View, F

TypeScript后端数据正确映射为前端接口类型的方法
前端开发 · 2026-07-01

TypeScript后端数据正确映射为前端接口类型的方法

在后端数据与前端类型之间来回转换,几乎是每位 TypeScript 开发者都无法回避的常态。后端返回的 car_brand、reg_number,和前端接口中定义的 brand、govtNumber,命名风格常常对不上号。此时,如果为了省事直接用 as 类型断言“强行”指认类型,那就踩进了常见的陷阱

动态HTML表格按层级条件合并单元格的JavaScript实现
前端开发 · 2026-07-01

动态HTML表格按层级条件合并单元格的JavaScript实现

本文详细讲解一种递归式 JavaScript 合并单元格方法,用于按列优先级(如前3列)智能合并表格行:仅当前一列已合并的前提下,才允许后续列合并相同值,从而精准实现多级分组与层级表格合并效果。 在动态生成的 HTML 表格中,按业务逻辑合并重复行是常见需求。然而,简单地对单列分别遍历合并——例如先

Next.js 13+重定向后滚动失效解决方案
前端开发 · 2026-07-01

Next.js 13+重定向后滚动失效解决方案

在 Next js App Router 的日常开发中,有一个令人颇为困扰的异常现象——当服务端执行 `redirect()` 跳转后,目标页面竟然无法正常滚动。没错,页面已经渲染完成,内容也完整显示,但垂直滚动条仿佛凭空消失。这个问题在 Next js 13 5 4 版本中尤为突出。 先给出结论:

WebGL图像加载延迟的纹理初始化时立即显示方法
前端开发 · 2026-07-01

WebGL图像加载延迟的纹理初始化时立即显示方法

本文详细介绍如何利用 Promise 与 async await 重构 WebGL 纹理加载流程,彻底解决首次渲染显示蓝色占位色、需要手动交互才能刷新的问题,实现文件导入后四张纹理平面即时正确渲染。 实际上,这个坑在 WebGL 开发中相当常见——纹理异步加载的小陷阱,说起来不大,但第一次遇到确实令