You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单页多圆形进度条实现问题求助

多圆形进度条解决方案

以下是修改后的完整代码,解决单页多进度条的复用问题:

完整代码示例

HTML

<div class="progress-container">
  <canvas class="progress-canvas" width="400" height="400"></canvas>
  <span class="progress-percent" data-target="6289">0</span>
</div>
<div class="progress-container">
  <canvas class="progress-canvas" width="400" height="400"></canvas>
  <span class="progress-percent" data-target="3000">0</span>
</div>
<div class="progress-container">
  <canvas class="progress-canvas" width="400" height="400"></canvas>
  <span class="progress-percent" data-target="1500">0</span>
</div>

CSS

.progress-container {
  position: relative;
  display: inline-block;
  margin: 20px;
}
.progress-percent {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 24px;
  font-weight: bold;
  color: #55c800;
}

JavaScript

window.onload = function() {
  // 获取所有进度条容器
  const containers = document.querySelectorAll('.progress-container');
  
  containers.forEach(container => {
    const canvas = container.querySelector('.progress-canvas');
    const percentSpan = container.querySelector('.progress-percent');
    const targetPercent = parseInt(percentSpan.dataset.target, 10);
    
    initProgressBar(canvas, percentSpan, targetPercent);
  });
};

function initProgressBar(canvas, percentSpan, targetPercent) {
  const c = canvas.getContext('2d');
  const posX = canvas.width / 2;
  const posY = canvas.height / 2;
  const fps = 2000 / 150; // 控制动画速度
  let degrees = 0;
  // 计算每1度对应的百分比
  const oneDegreePercent = targetPercent / 360;
  const totalDegrees = 360;
  
  c.lineCap = 'round';
  
  function arcMove() {
    const interval = setInterval(() => {
      degrees += 1;
      c.clearRect(0, 0, canvas.width, canvas.height);
      
      // 计算当前进度百分比
      const currentPercent = degrees * oneDegreePercent;
      percentSpan.textContent = Math.min(currentPercent.toFixed(), targetPercent);
      
      // 绘制背景圆环
      c.beginPath();
      c.arc(posX, posY, 140, (Math.PI / 180) * 270, (Math.PI / 180) * (270 + 360));
      c.strokeStyle = '#55c800';
      c.lineWidth = 5;
      c.stroke();
      
      // 绘制进度圆环
      c.beginPath();
      c.strokeStyle = '#55c800';
      c.lineWidth = 10;
      c.arc(posX, posY, 140, (Math.PI / 180) * 270, (Math.PI / 180) * (270 + degrees));
      c.stroke();
      
      // 达到目标后停止动画
      if (degrees >= totalDegrees) {
        clearInterval(interval);
        percentSpan.textContent = targetPercent;
      }
    }, fps);
  }
  
  arcMove();
}

关键改动说明

  1. 复用化结构

    • 用类名替代id(.progress-canvas、.progress-percent),避免id唯一性限制
    • 每个进度条放在独立容器.progress-container中,通过data-target属性自定义目标百分比
  2. 独立初始化逻辑

    • 封装initProgressBar函数,每个进度条的canvas、文本节点、目标值都是独立传入的
    • 用forEach遍历所有容器,逐个初始化进度条,确保每个动画互不干扰
  3. 动态百分比计算

    • 去掉硬编码的目标值,改为从data-target读取,支持不同进度条设置不同目标
    • 修正百分比计算逻辑,确保动画转满一圈时,文本显示准确的目标值
  4. 细节优化

    • 动画结束后强制设置文本为目标值,避免计算精度偏差
    • 添加CSS让进度数字居中显示,优化视觉效果

内容的提问来源于stack exchange,提问作者vicartdesign

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:15:35