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

React中如何根据线性渐变色修改SVG环形进度条描边色

SVG环形进度条动态描边色实现方案

核心逻辑基于RGB通道线性插值计算渐变对应位置色值,无第三方依赖,完全兼容现有React+SVG代码结构,不需要硬编码全量进度色值。

1. 封装渐变取色工具函数

先定义和现有CSS渐变完全匹配的色标节点,通过两点间RGB值线性插值,计算任意百分比进度对应的精确色值:

// 十六进制色值转RGB数组
const hexToRgb = (hex) => {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? [
    parseInt(result[1], 16),
    parseInt(result[2], 16),
    parseInt(result[3], 16)
  ] : [0,0,0];
}

// RGB数组转十六进制色值
const rgbToHex = (r,g,b) => 
  `#${((1<<24) + (r<<16) + (g<<8) + b).toString(16).slice(1)}`;

// 渐变配置,和已有CSS linear-gradient参数完全对应
const gradientStops = [
  { pos: 0, color: '#99da98' },
  { pos: 51.56, color: '#f8b66a' },
  { pos: 100, color: '#cf6767' }
];

// 根据进度百分比获取对应渐变位置色值
const getProgressColor = (percent) => {
  // 边界值处理
  if(percent <= 0) return gradientStops[0].color;
  if(percent >= 100) return gradientStops.at(-1).color;

  // 定位当前进度所属的色段区间
  for(let i = 0; i < gradientStops.length - 1; i++) {
    const startStop = gradientStops[i];
    const endStop = gradientStops[i+1];
    if(percent >= startStop.pos && percent <= endStop.pos) {
      // 计算当前位置在色段内的权重占比
      const range = endStop.pos - startStop.pos;
      const weight = (percent - startStop.pos) / range;
      // 对RGB三个颜色通道分别做线性插值
      const [r1,g1,b1] = hexToRgb(startStop.color);
      const [r2,g2,b2] = hexToRgb(endStop.color);
      const r = Math.round(r1 + (r2 - r1)*weight);
      const g = Math.round(g1 + (g2 - g1)*weight);
      const b = Math.round(b1 + (b2 - b1)*weight);
      return rgbToHex(r,g,b);
    }
  }
  return gradientStops[0].color;
}

2. 修改SVG组件代码

将原进度条路径写死的stroke属性替换为动态取色调用,传入当前进度值即可:

<svg viewBox="0 0 36 36" className="circular-chart">
  <path className="svg-back"
    fill='none'
    stroke={props.theme.colors.Neutral.Gray1}
    strokeWidth={3}
    d="M18 2.0845
  a 15.9155 15.9155 0 0 1 0 31.831
  a 15.9155 15.9155 0 0 1 0 -31.831"
  />
  <path className="circle"
    stroke={getProgressColor(Number(props.percentage))}
    stroke-dasharray={`${props.percentage} 100`}
    d="M18 2.0845
  a 15.9155 15.9155 0 0 1 0 31.831
  a 15.9155 15.9155 0 0 1 0 -31.831"
  />

  <text
    x={18}
    y={21}
    className="svg-circle-text">
    {props.percentage}%
  </text>
</svg>

注意:如果传入的props.percentage是字符串格式,必须先转为数值类型再传入取色函数,避免插值计算异常。

3. 调整原有CSS

删除.circle类中写死的描边色规则,避免覆盖JS动态设置的属性:

.svg-circle-text {
  font-size: 0.5rem;
  text-anchor: middle;
  fill: ${theme.colors.Primary.Black};
  font-weight: bold;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle {
  /* 移除原代码中写死的 stroke: #99DA98; 规则 */
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

效果说明

  • 进度0%时描边为渐变起点浅绿色#99da98
  • 进度51.56%时描边为渐变中间橙色#f8b66a
  • 进度100%时描边为渐变终点浅红色#cf6767
  • 任意中间进度(如60%)会自动计算对应过渡色,和定义的90度线性渐变同位置色值完全一致
  • 原有进度加载动画、文本显示、背景轨道样式全部保留,不需要额外调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:57:19