使用 svg 圆圈和文本在饼图中围绕中心对齐文本

Aligning text around center in pie chart using svg circle and text

我使用 React 和 svg 圆圈创建了一个饼图。现在我想定位文本标签,使文本从靠近圆圈的中间开始并继续向外延伸,命运之轮样式。

这是我的代码,渲染 svg。在 chrome 开发工具中,我尝试应用 tranform: rotate(45deg); 并调整数字,但文本一直飞到圆圈外。

<svg viewBox="0 0 32 32">
    {elements.map((element, index) => (
        <g>
            <circle
                key={_id}
                r={16 / 1.0053}
                cx={'50%'}
                cy={'50%'}
                style={{
                    strokeDasharray: `${percentage}, 100.53`,
                    strokeDashoffset: -offset,
                    stroke: segmentColor,
                }}
                textAnchor="middle"
            ></circle>
            <text
                textAnchor="middle"
                x={'50%'}
                y={'50%'}
                fontFamily={'sans-serif'}
                fontSize={'20px'}
                fill="black"
                textAnchor="start"
            >
                {title}
            </text>
        </g>
    ))}
</svg>
``` 

问题在于旋转是关于原点的,即图像的左上角。解决此问题的最简单方法是更改​​ viewBox,使原点位于 SVG 的中心:viewBox="-16 -16 32 32".

然后你根据偏移量和百分比计算角度。

我假设你有一些像这样的元素:

const elements = [
    { percentage: 15, offset: 0, title: 'title', segmentColor: 'red' },
    { percentage: 40, offset: 15, title: 'another title', segmentColor: 'blue' },
    { percentage: 25, offset: 55, title: 'and another', segmentColor: 'green' },
    { percentage: 20, offset: 80, title: 'yet another', segmentColor: 'black' },
];

所以这样的事情会起作用:

<svg viewBox="-16 -16 32 32">
    {elements.map((element, index) => {
        const angle = (element.offset + element.percentage / 2) * 360 / 100;

        return <g key={index}>
            <circle
                r={15.5}
                style={{
                    fill: 'none',
                    strokeDasharray: `${element.percentage}, 100.53`,
                    strokeDashoffset: -element.offset,
                    stroke: element.segmentColor,
                }}
                textAnchor="middle"
            ></circle>
            <text
                x="10%"
                transform={`rotate(${angle})`}
                fontFamily={'sans-serif'}
                fontSize={'2px'}
                fill="black"
                textAnchor="start"
                alignmentBaseline="middle"
            >
                {element.title}
            </text>
        </g>
    })}
</svg>

现在,文本上的 x 值决定了文本从中心开始的位置。