使用react-native-svg实现分段环形进度条出现显示异常求助
修复自定义分段环形进度条问题
核心问题定位
你的代码大概率没有正确累加每个分段的起始角度,导致所有分段都从同一个初始角度绘制,互相覆盖后只留下重复显示的紫色分段,其余分段被完全遮挡。
修复后的完整组件代码
import React from 'react'; import { View } from 'react-native'; import Svg, { Path } from 'react-native-svg'; const SegmentedRingProgress = ({ segments, // 数据格式:[{ value: 数值, color: 颜色 }, ...] radius = 100, strokeWidth = 20, startAngle = -90, // 起始角度(-90对应环形顶部) }) => { const totalValue = segments.reduce((sum, seg) => sum + seg.value, 0); const centerX = radius + strokeWidth / 2; const centerY = radius + strokeWidth / 2; const outerRadius = radius; const innerRadius = radius - strokeWidth; // 角度转弧度工具函数 const degToRad = (deg) => (deg * Math.PI) / 180; // 生成单个分段的环形路径 const getArcPath = (startDeg, endDeg, isLargeArc) => { const startRad = degToRad(startDeg); const endRad = degToRad(endDeg); // 外弧起止点坐标 const startX = centerX + outerRadius * Math.cos(startRad); const startY = centerY + outerRadius * Math.sin(startRad); const endX = centerX + outerRadius * Math.cos(endRad); const endY = centerY + outerRadius * Math.sin(endRad); // 内弧起止点坐标 const innerStartX = centerX + innerRadius * Math.cos(startRad); const innerStartY = centerY + innerRadius * Math.sin(startRad); const innerEndX = centerX + innerRadius * Math.cos(endRad); const innerEndY = centerY + innerRadius * Math.sin(endRad); // 拼接SVG路径命令:外弧→内弧→闭合路径 return ` M ${startX} ${startY} A ${outerRadius} ${outerRadius} 0 ${isLargeArc ? 1 : 0} 1 ${endX} ${endY} L ${innerEndX} ${innerEndY} A ${innerRadius} ${innerRadius} 0 ${isLargeArc ? 1 : 0} 0 ${innerStartX} ${innerStartY} Z `; }; let currentAngle = startAngle; return ( <View> <Svg width={radius * 2 + strokeWidth} height={radius * 2 + strokeWidth} > {segments.map((segment, index) => { // 计算当前分段占总环形的角度 const segmentAngle = (segment.value / totalValue) * 360; const endAngle = currentAngle + segmentAngle; // 处理大于180度的分段,确保SVG路径绘制正确 const isLargeArc = segmentAngle > 180 ? 1 : 0; const path = getArcPath(currentAngle, endAngle, isLargeArc); // 更新下一个分段的起始角度 currentAngle = endAngle; return ( <Path key={index} d={path} fill={segment.color} /> ); })} </Svg> </View> ); }; export default SegmentedRingProgress;
使用示例(App.js)
import SegmentedRingProgress from './SegmentedRingProgress'; // 你的分段数据示例 const ringSegments = [ { value: 30, color: '#FF6B6B' }, { value: 25, color: '#4ECDC4' }, { value: 20, color: '#FFE66D' }, { value: 25, color: '#95E1D3' }, ]; // 组件调用 <SegmentedRingProgress segments={ringSegments} radius={80} strokeWidth={15} startAngle={-90} />
关键修复点
- 新增
currentAngle变量,每个分段绘制完成后更新为当前分段的结束角度,确保下一个分段从正确位置开始 - 每个分段使用独立的闭合环形路径(外弧+内弧+闭合命令),彻底避免分段重叠遮挡
- 处理了大于180度的分段场景,通过
isLargeArc参数保证路径绘制正确
内容的提问来源于stack exchange,提问作者Sani
相关产品推荐
相关产品推荐

