React中使用SVG定位环形图分段及添加文本的问题
SVG环形分段定位与文本添加(React环境)
问题描述
在React中编写的SVG环形图代码如下,尝试将绿色环形分段旋转至90°、180°和270°位置时,修改rotate或translate属性后分段会消失。需要解决:
- 如何正确定位12.5%的环形分段到指定角度
- 如何为每个分段添加文本标注
const Donut = () => { return ( <div className='rounded p-20' > <svg height="30em" width="30em" viewBox="0 0 20 20"> <circle r="10" cx="10" cy="10" fill="white" /> <circle r="5" cx="10" cy="10" fill="bisque" stroke="tomato" stroke-width="10" stroke-dasharray="calc(12.5 * 31.42 / 100) 31.42" transform="rotate(-90) translate(-20)" /> <circle r="5" cx="10" cy="10" fill="none" stroke="green" stroke-width="10" stroke-dasharray="calc(12.5 * 31.42 / 100) 31.42" transform="rotate(90) translate(-20)" /> <circle r="5" cx="10" cy="10" fill="white" /> </svg> </div> ) }
一、解决环形分段定位问题
问题原因
之前的transform="rotate(XX) translate(-20)"顺序错误:SVG的transform是从右到左执行,先执行translate(-20)再执行旋转,导致旋转中心偏移到SVG viewBox之外,修改角度后分段会被移出可见区域。
正确定位方法
应将旋转中心固定为环形的圆心(10,10),通过translate先把坐标系原点移到圆心,旋转后再移回,确保旋转始终围绕圆心进行:
transform="translate(10,10) rotate(起始角度) translate(-10,-10)"
关键参数说明:
- 12.5%的分段对应45°范围(360°×12.5%=45°)
- SVG默认0°在右侧,角度顺时针递增:顶部为-90°(或270°)、底部为90°、左侧为180°
修正后的分段代码示例
将绿色分段分别定位到90°(底部)、180°(左侧)、270°(顶部)的代码:
// 番茄色分段:顶部起始(-90°) <circle r="5" cx="10" cy="10" fill="bisque" stroke="tomato" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(-90) translate(-10,-10)" /> // 绿色分段:底部起始(90°) <circle r="5" cx="10" cy="10" fill="none" stroke="green" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(90) translate(-10,-10)" /> // 绿色分段:左侧起始(180°) <circle r="5" cx="10" cy="10" fill="none" stroke="green" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(180) translate(-10,-10)" /> // 绿色分段:顶部起始(270°) <circle r="5" cx="10" cy="10" fill="none" stroke="green" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(270) translate(-10,-10)" />
二、为分段添加文本标注
利用SVG的<text>元素,通过三角函数计算分段中心坐标,设置文本居中对齐:
- 计算分段中心角度:
起始角度 + 22.5°(45°分段的中点偏移量) - 将角度转为弧度:
Math.PI / 180 * 中心角度 - 计算文本坐标:取环形中间半径7.5(外半径10、内半径5的中间值),则:
x = 10 + 7.5 * Math.cos(弧度)y = 10 + 7.5 * Math.sin(弧度)
- 设置
textAnchor="middle"和dominantBaseline="middle"确保文本居中
带文本的完整代码示例
const Donut = () => { // 计算文本位置的工具函数 const getTextPosition = (startAngle) => { const centerAngle = startAngle + 22.5; const radian = Math.PI / 180 * centerAngle; const radius = 7.5; return { x: 10 + radius * Math.cos(radian), y: 10 + radius * Math.sin(radian) }; }; return ( <div className='rounded p-20'> <svg height="30em" width="30em" viewBox="0 0 20 20"> {/* 背景圆环 */} <circle r="10" cx="10" cy="10" fill="white" /> {/* 番茄色分段 + 文本 */} <circle r="5" cx="10" cy="10" fill="bisque" stroke="tomato" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(-90) translate(-10,-10)" /> <text {...getTextPosition(-90)} textAnchor="middle" dominantBaseline="middle" fontSize="1.5em" fill="tomato"> 12.5% </text> {/* 绿色分段(底部) + 文本 */} <circle r="5" cx="10" cy="10" fill="none" stroke="green" strokeWidth="10" strokeDasharray="calc(12.5 * 31.42 / 100) 31.42" transform="translate(10,10) rotate(90) translate(-10,-10)" /> <text {...getTextPosition(90)} textAnchor="middle" dominantBaseline="middle" fontSize="1.5em" fill="green"> 12.5% </text> {/* 中心遮罩圆 */} <circle r="5" cx="10" cy="10" fill="white" /> </svg> </div> ) }
补充说明
stroke-dasharray中的31.42是环形周长(2×π×5≈31.42),如需更精确可替换为calc(2 * 3.1416 * 5)- React中SVG属性建议用驼峰式命名(如
strokeWidth代替stroke-width),更符合React规范
内容的提问来源于stack exchange,提问作者psykx
相关产品推荐
相关产品推荐

