Размещение linear gradient в circle исходя из процентов заполнения
Требуется реализовать данный комопнент:
Пока сделал такой компонент в react но теперьб не знаю как правильно расчитать позиционированния градиента, может кто-то поможет?
Пример кода:
body {
background: black;
}
<script src="https://cdn.tailwindcss.com"></script>
<div class='relative size-52'>
<svg fill="none" class="size-full -rotate-90" stroke-width="2" view-box="0 0 212 212">
<defs>
<linearGradient id="circle-gradient" x1="100%" y1="0%" x2="0%" y2="100%">
<stop offset="60%" stop-opacity="0" stop-color="white" />
<stop offset="75%" stop-opacity="1" stop-color="white" />
</linearGradient>
</defs>
<circle
cx="106"
cy="106"
r="90"
stroke-width="12"
stroke="url(#circle-gradient)"
stroke-dasharray="282.7433388230814 282.743338823"
class="opacity-100"
/>
<circle cx="106" cy="106" r="90" stroke-width="12" class="opacity-30 stroke-white" />
<circle cx="16" cy="106.00000000000001" r="12" fill="white" class="drop-shadow" />
</svg>
<div class="absolute inset-0 m-auto size-fit p-4 text-center text-white text-[48px] font-bold">
40
</div>
</div>
Код компонента:
import React, { ReactNode } from 'react';
import { cn } from '@/lib/utils';
const CircleCountdown = ({
max = 100,
min = 0,
value = 0,
className = '',
children,
}: {
value: number
max?: number
min?: number
className?: string
children?: ReactNode
}) => {
const percent = ((value - min) / (max - min)) * 100;
const circumference = 2 * 90 * Math.PI;
const draw = percent * circumference / 100;
const angle = (percent / 100) * 2 * Math.PI;
const endX = 106 + 90 * Math.cos(angle);
const endY = 106 + 90 * Math.sin(angle);
return (
<div className={cn('relative size-52', className)}>
<svg fill="none" className="size-full -rotate-90" strokeWidth="2" viewBox="0 0 212 212">
<defs>
<linearGradient id="circle-gradient" x1="100%" y1="0%" x2="0%" y2="100%">
<stop offset="60%" stopOpacity="0" stopColor="white" />
<stop offset="75%" stopOpacity="1" stopColor="white" />
</linearGradient>
</defs>
<circle
cx="106"
cy="106"
r="90"
strokeWidth="12"
stroke="url(#circle-gradient)"
strokeDasharray={`${draw} ${circumference - draw}`}
className="opacity-100"
/>
<circle cx="106" cy="106" r="90" strokeWidth="12" className="opacity-30 stroke-white" />
<circle cx={endX} cy={endY} r="12" fill="white" className="drop-shadow" />
</svg>
<div className="absolute inset-0 m-auto size-fit p-4 text-center">
{children}
</div>
</div>
);
};
export { CircleCountdown };