Files
Ruleta_Actvidad/src/components/game/Ruleta/RuletaSVG.tsx
T

100 lines
3.0 KiB
TypeScript
Raw Normal View History

2026-07-25 01:35:36 -06:00
import type { Categoria } from '../../../types'
interface RuletaSVGProps {
categorias: Categoria[]
rotacion: number
isSpinning: boolean
onClick: () => void
}
export default function RuletaSVG({ categorias, rotacion, isSpinning, onClick }: RuletaSVGProps) {
const cx = 200
const cy = 200
const r = 180
const total = categorias.length
const angleStep = 360 / total
function polarToCartesian(angle: number, radius: number) {
const rad = (angle - 90) * (Math.PI / 180)
return {
x: cx + radius * Math.cos(rad),
y: cy + radius * Math.sin(rad),
}
}
function sectorPath(startAngle: number, endAngle: number) {
const start = polarToCartesian(startAngle, r)
const end = polarToCartesian(endAngle, r)
const largeArc = endAngle - startAngle > 180 ? 1 : 0
return `M ${cx} ${cy} L ${start.x} ${start.y} A ${r} ${r} 0 ${largeArc} 1 ${end.x} ${end.y} Z`
}
return (
<div className="relative flex items-center justify-center">
{/* Indicador */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-2 z-10">
<div className="w-0 h-0 border-l-[12px] border-r-[12px] border-t-[24px] border-l-transparent border-r-transparent border-t-gray-800 drop-shadow-md" />
</div>
{/* Ruleta SVG */}
<svg
width="400"
height="400"
viewBox="0 0 400 400"
onClick={!isSpinning ? onClick : undefined}
className={`select-none drop-shadow-xl ${!isSpinning ? 'cursor-pointer' : 'cursor-not-allowed'}`}
style={{
transition: 'transform 4s cubic-bezier(0.25, 0.1, 0.25, 1)',
transform: `rotate(${rotacion}deg)`,
}}
>
{categorias.map((cat, i) => {
const startAngle = i * angleStep
const endAngle = startAngle + angleStep
const midAngle = startAngle + angleStep / 2
const textPos = polarToCartesian(midAngle, r * 0.62)
return (
<g key={cat.id}>
{/* Sector */}
<path
d={sectorPath(startAngle, endAngle)}
fill={cat.color}
stroke="white"
strokeWidth="3"
/>
{/* Emoji */}
<text
x={textPos.x}
y={textPos.y - 14}
textAnchor="middle"
dominantBaseline="middle"
fontSize="28"
>
{cat.emoji}
</text>
{/* Nombre */}
<text
x={textPos.x}
y={textPos.y + 16}
textAnchor="middle"
dominantBaseline="middle"
fontSize="13"
fontWeight="bold"
fill="white"
>
{cat.nombre}
</text>
</g>
)
})}
{/* Centro */}
<circle cx={cx} cy={cy} r={22} fill="white" stroke="#e5e7eb" strokeWidth="3" />
<circle cx={cx} cy={cy} r={10} fill="#7C3AED" />
</svg>
</div>
)
}