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

如何构建带进度与轨道间隙的React圆形进度条

React 实现带间隙的圆形进度条组件

要实现进度段与轨道段之间的间隙效果,核心是利用SVG的stroke-dasharray和stroke-dashoffset属性,让轨道和进度圆环的间隙位置完全对齐。以下是具体实现方案:

核心思路

  1. 用两个SVG <circle> 元素分别实现轨道和进度条:
    • 轨道圆环通过stroke-dasharray定义线段与间隙的长度,形成带间隙的环形轨道。
    • 进度圆环使用相同的stroke-dasharray,通过stroke-dashoffset控制显示的进度长度,确保进度段与轨道的间隙完美对齐。
  2. 通过rotate(-90deg)让进度从顶部开始,符合常规视觉习惯;用strokeLinecap="round"让进度段两端呈现圆角,匹配设计风格。

完整组件代码

import React from 'react';

const CircularProgressBar = ({ 
  percentage, 
  radius = 80, 
  strokeWidth = 12, 
  segments = 12, 
  gapRatio = 0.2 
}) => {
  const circumference = 2 * Math.PI * radius;
  // 计算单段间隙的弧长(按占单段总角度的比例)
  const segmentTotalAngle = 360 / segments;
  const gapAngle = segmentTotalAngle * gapRatio;
  const segmentAngle = segmentTotalAngle - gapAngle;

  const segmentLength = (segmentAngle / 360) * circumference;
  const gapLength = (gapAngle / 360) * circumference;
  // 计算进度的总显示长度(扣除所有间隙后的有效周长 × 百分比)
  const progressTotalLength = (circumference - segments * gapLength) * (percentage / 100);

  return (
    <svg 
      width={radius * 2} 
      height={radius * 2} 
      viewBox={`0 0 ${radius * 2} ${radius * 2}`}
    >
      {/* 带间隙的轨道圆环 */}
      <circle
        cx={radius}
        cy={radius}
        r={radius - strokeWidth / 2}
        fill="none"
        stroke="#e0e0e0"
        strokeWidth={strokeWidth}
        strokeDasharray={`${segmentLength} ${gapLength}`}
        strokeLinecap="round"
      />
      {/* 进度圆环 */}
      <circle
        cx={radius}
        cy={radius}
        r={radius - strokeWidth / 2}
        fill="none"
        stroke="#2196F3"
        strokeWidth={strokeWidth}
        strokeDasharray={`${segmentLength} ${gapLength}`}
        strokeDashoffset={circumference - progressTotalLength}
        strokeLinecap="round"
        transform={`rotate(-90 ${radius} ${radius})`}
        style={{ transition: 'stroke-dashoffset 0.3s ease-in-out' }}
      />
      {/* 中间百分比文本 */}
      <text
        x={radius}
        y={radius}
        textAnchor="middle"
        dominantBaseline="middle"
        fontSize={radius / 3}
        fontWeight="bold"
      >
        {`${Math.round(percentage)}%`}
      </text>
    </svg>
  );
};

export default CircularProgressBar;

参数说明与自定义调整

  • percentage:必填,进度百分比(0-100)。
  • radius:可选,圆形进度条的半径,默认80。
  • strokeWidth:可选,圆环的线条宽度,默认12。
  • segments:可选,轨道/进度的分段数量,默认12,数值越大间隙越密集。
  • gapRatio:可选,间隙占单段总角度的比例(0-1),默认0.2,数值越大间隙越宽。

使用示例

// 在项目中引入并使用
<CircularProgressBar 
  percentage={65} 
  radius={100} 
  strokeWidth={15} 
  segments={16} 
  gapRatio={0.15}
/>

关键细节解释

  • stroke-dasharray:轨道和进度圆环共用相同的线段/间隙长度配置,确保两者的间隙位置完全对应。
  • stroke-dashoffset:通过计算circumference - progressTotalLength,让进度从顶部开始逐步显示,百分比越高,偏移值越小,进度越长。
  • 过渡动画:给进度圆环添加transition属性,实现进度变化时的平滑动画效果。

内容的提问来源于stack exchange,提问作者Ümit Aparı

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:02:10