Проблема с лейблом Recharts (React.JS)

Столкнулся с проблемой реализации подчеркивания текста в библиотеке Recharts, график Pie Chart, должно выглядеть вот так: введите сюда описание изображения

У меня получается так: введите сюда описание изображения

Код прикрепляю:

import React from 'react';
import clsx from 'clsx';
import { Cell, Pie, PieChart, PieLabel, ResponsiveContainer } from 'recharts';
import { Button } from 'shared/components/Button';
import { Label } from 'shared/components/Label';
import ArrowRightIcon from 'shared/icons/ArrowRight.icon';
import DocumentSicon from 'shared/icons/static/Document.sicon';
import css from './Tokenomics.module.scss';

const data = [
    { name: 'Gevulot Labs', value: 10.6 },
    { name: 'Investors', value: 19.3 },
    { name: 'Team', value: 20 },
    { name: 'Foundation reserve', value: 10.7 },
    { name: 'Market makers', value: 2 },
    { name: 'Partnership agreements', value: 10 },
    { name: 'Grants', value: 0.6 },
    { name: 'Delegations', value: 24 },
];

const colors = [
    '#90A0E2',
    '#B3BCEA',
    '#CDD7FB',
    '#DFE6FF',
    '#EAEFFF',
    '#F0F3FF',
    '#4C66D4',
    '#F1F2F8',
    '#90A0E2',
];

const RADIAN = Math.PI / 180;

const renderLabelLine = ({ cx, cy, midAngle, outerRadius }: any) => {
    const RADIAN = Math.PI / 180;
    const angle = -midAngle * RADIAN;

    // Исходные координаты от внешнего края сектора
    const startX = cx + outerRadius * Math.cos(angle);
    const startY = cy + outerRadius * Math.sin(angle);

    // Точка сгиба
    const bendX = cx + (outerRadius + 10) * Math.cos(angle);
    const bendY = cy + (outerRadius + 10) * Math.sin(angle);

    const isLeft = bendX < cx;
    const labelLineLength = 40;
    const lineEndX = isLeft ? bendX - labelLineLength : bendX + labelLineLength;
    const lineEndY = bendY;

    // Путь с изгибом и горизонтальной линией
    const d = `
      M ${startX},${startY}
      Q ${bendX},${bendY} ${lineEndX},${lineEndY}
    `;

    // Подчёркивание (жирная синяя линия)
    const underlineStartX = isLeft ? lineEndX - 30 : lineEndX;
    const underlineEndX = isLeft ? lineEndX : lineEndX + 30;

    return (
        <g>
            {/* Пунктирная линия с изгибом */}
            <path d={d} stroke="#C8D1E1" strokeWidth={2} fill="none" strokeDasharray="6 6" />
            {/* Подчеркивание под текстом */}
            <line
                x1={underlineStartX}
                y1={lineEndY}
                x2={underlineEndX}
                y2={lineEndY}
                stroke="#4D7CFE"
                strokeWidth={3}
            />
        </g>
    );
};

const renderLabel = ({ cx, cy, midAngle, outerRadius, index }: any) => {
    const RADIAN = Math.PI / 180;
    const angle = -midAngle * RADIAN;
    const radius = outerRadius + 50;
    const x = cx + radius * Math.cos(angle);
    const y = cy + radius * Math.sin(angle);
    const isLeft = x < cx;
    const textAnchor = isLeft ? 'end' : 'start';

    return (
        <text
            x={x}
            y={y}
            textAnchor={textAnchor}
            dominantBaseline="middle"
            fontSize="16"
            fill="#000"
        >
            <tspan x={x} dy="-0.6em" className={css.label_percentage} fontWeight="bold">
                {data[index].value}%
            </tspan>
            <tspan x={x} dy="1.6em" className={css.label_title} fill="#777">
                {data[index].name}
            </tspan>
        </text>
    );
};

export const Tokenomics: React.FC = () => {
    return (
        <div className={css.tokenomics}>
            <div className={css.tokenomics_container}>
                <div className={css.tokenomics_chart}>
                    <ResponsiveContainer width="100%" height="100%">
                        <PieChart>
                            <Pie
                                data={data}
                                cx="50%"
                                cy="50%"
                                label={renderLabel}
                                labelLine={renderLabelLine}
                                outerRadius="57.4%"
                                innerRadius="30%"
                                paddingAngle={3}
                                cornerRadius="15%"
                                fill="#8884d8"
                                dataKey="value"
                            >
                                {data.map((_, index) => (
                                    <Cell
                                        key={`cell-${index}`}
                                        fill={colors[index & colors.length]}
                                        stroke="#FFF"
                                    />
                                ))}
                            </Pie>
                        </PieChart>
                    </ResponsiveContainer>
                </div>
            </div>
        </div>
    );
};

CSS:

.label_percentage {
    font-size: "TasaOrbiterDisplay";
    font-weight: 500;
    font-size: 32px;
    line-height: 1.3;
    letter-spacing: -0.04em;
    color: #000;
}
.label_title {
    font-family: "Aspekta";
    font-weight: 500;
    font-size: 14px;
    line-height: 1.45;
    letter-spacing: -0.03em;
    color: #000;
    opacity: 0.6;
}

CodeSandbox: https://codesandbox.io/p/devbox/delicate-sun-lnvqkg?file=%2Fsrc%2Fstyles.css&workspaceId=ws_QyKMbtfzZ89mpAdWxtqWKL

Возможно ли довести это все до вида с первого скрина, чтобы пунктирная линия была от колонки и вела ПОД текст? Буду благодарен за помощь.


Ответы (0 шт):