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

React环形进度组件开发求助:匹配指定设计需求

实现方案与库推荐

一、纯React+SVG实现(最贴合需求)

SVG对环形进度类组件的支持更灵活,能精准控制填充范围和虚线标记,以下是实现代码:

import React from 'react';

const DoughnutComponent = ({ percent }) => {
  // 映射百分比到角度:0-200%对应0-360°
  const fillAngle = Math.min((percent / 200) * 360, 360);
  const fillRadians = (fillAngle * Math.PI) / 180;
  const center = 50;
  const innerRadius = 30;
  const outerRadius = 40;
  const dashRadius = 42;

  // 生成填充路径
  let fillPath = '';
  if (fillAngle > 0) {
    if (fillAngle <= 180) {
      // 0-100%:填充到虚线标记位置
      const endX = center + outerRadius * Math.cos(fillRadians - Math.PI/2);
      const endY = center + outerRadius * Math.sin(fillRadians - Math.PI/2);
      fillPath = `M ${center},${center - outerRadius} A ${outerRadius},${outerRadius} 0 0,1 ${endX},${endY} L ${center},${center} Z`;
    } else {
      // 100%-200%:先填满内圈,再填充外圈剩余部分
      const remainingAngle = fillAngle - 180;
      const remainingRadians = (remainingAngle * Math.PI) / 180;
      const outerEndX = center + outerRadius * Math.cos(remainingRadians + Math.PI/2);
      const outerEndY = center + outerRadius * Math.sin(remainingRadians + Math.PI/2);
      fillPath = `M ${center},${center - outerRadius} A ${outerRadius},${outerRadius} 0 1,1 ${center},${center + outerRadius} L ${center},${center} Z M ${center},${center + outerRadius} A ${outerRadius},${outerRadius} 0 0,1 ${outerEndX},${outerEndY} L ${center},${center} Z`;
    }
  }

  // 100%标记虚线路径
  const dashPath = `M ${center},${center - dashRadius} A ${dashRadius},${dashRadius} 0 1,1 ${center},${center + dashRadius}`;

  return (
    <svg width="100" height="100" viewBox="0 0 100 100">
      {/* 底层白色环形 */}
      <circle cx={center} cy={center} r={outerRadius} fill="#fff" stroke="#eee" strokeWidth="10" />
      {/* 橙色填充区域 */}
      {fillAngle > 0 && <path d={fillPath} fill="#ff7f24" />}
      {/* 100%虚线标记 */}
      <path d={dashPath} fill="none" stroke="#ccc" strokeWidth="1" strokeDasharray="2,3" />
    </svg>
  );
};

export default DoughnutComponent;

逻辑说明

  • 百分比与角度映射:200%对应360°全环形,100%对应180°(虚线位置)
  • 分两段处理填充:0-100%填充内半圈,100%-200%先填满内半圈再补全外半圈
  • 虚线标记通过strokeDasharray实现,无需额外DOM元素

二、改进的CSS方案(避免径向渐变问题)

之前用径向渐变失效是因为它无法精准控制环形的分段填充,改用锥形渐变+遮罩可以解决:

.doughnut-wrap {
  width: 200px;
  height: 200px;
  position: relative;
  border-radius: 50%;
  /* 遮罩实现环形镂空 */
  mask: radial-gradient(circle, transparent 60%, black 60%);
  -webkit-mask: radial-gradient(circle, transparent 60%, black 60%);
}

.doughnut-fill {
  width: 100%;
  height: 100%;
  /* 锥形渐变控制填充角度 */
  background: conic-gradient(#ff7f24 0deg var(--fill-angle), transparent var(--fill-angle) 360deg);
}

.doughnut-dash {
  position: absolute;
  top: -4px;
  left: 50%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ccc;
  transform: translateX(-50%);
}
/* 垂直虚线标记 */
.doughnut-dash::after {
  content: '';
  position: absolute;
  top: 8px;
  left: 50%;
  width: 1px;
  height: 208px;
  background: repeating-linear-gradient(transparent, transparent 3px, #ccc 3px, #ccc 5px);
  transform: translateX(-50%);
}

React组件中动态设置角度变量:

const DoughnutComponent = ({ percent }) => {
  const fillAngle = Math.min((percent / 200) * 360, 360);
  return (
    <div className="doughnut-wrap" style={{ '--fill-angle': `${fillAngle}deg` }}>
      <div className="doughnut-fill"></div>
      <div className="doughnut-dash"></div>
    </div>
  );
};

三、适配的第三方库推荐

如果不想手动实现,以下库可以快速满足需求:

  • Recharts:支持自定义环形进度条,可通过调整内外半径、起始角度、分段颜色实现设计,文档齐全且社区活跃
  • React Circular Progressbar:提供高度自定义的环形组件,支持多层环形、虚线标记,可直接映射百分比到填充范围
  • SVG.js:轻量级SVG操作库,适合需要复杂SVG路径控制的场景,能简化手动写SVG路径的工作量

内容的提问来源于stack exchange,提问作者pc-12345

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:50:17