Проблема в том, что вращение связано с источником, который находится в левом верхнем углу вашего изображения. Самый простой способ обойти это - изменить 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 в тексте определяет, как из центра начинается текст.