import { useCallback, useEffect, useRef, useState } from "react";
import { GlCanvas, Shape, Rect } from "react-thorvg-fiber";
import { gsap } from "gsap";
import wasmUrl from "react-thorvg-fiber/thorvg-gl.wasm?url";
// Pre-calculate static shape data
const SHAPE_COUNT = 1000;
const GRID_SIZE = Math.ceil(Math.sqrt(SHAPE_COUNT));
const CANVAS_SIZE = 500;
const SHAPE_SIZE = CANVAS_SIZE / GRID_SIZE;
const shapeData = Array.from({ length: SHAPE_COUNT }, (_, i) => {
const row = Math.floor(i / GRID_SIZE);
const col = i % GRID_SIZE;
const hue = (i * 360) / SHAPE_COUNT;
return {
key: `shape-${i}`,
x: col * SHAPE_SIZE + SHAPE_SIZE / 2,
y: row * SHAPE_SIZE + SHAPE_SIZE / 2,
color: hslToRgb(hue, 0.7, 0.6),
};
});
function hslToRgb(h: number, s: number, l: number): [number, number, number, number] {
// HSL to RGB conversion (implementation omitted for brevity)
// Returns [r, g, b, 255]
}
function OptimizedCanvas() {
const [rotation, setRotation] = useState(0);
const rotationRef = useRef({ value: 0 });
const locateFile = useCallback(() => wasmUrl, []);
useEffect(() => {
const tween = gsap.to(rotationRef.current, {
value: 360,
duration: 10,
repeat: -1,
ease: "none",
onUpdate: () => {
setRotation(rotationRef.current.value);
},
});
return () => tween.kill();
}, []);
return (
<GlCanvas
id="optimized-canvas"
width={CANVAS_SIZE}
height={CANVAS_SIZE}
devicePixelRatio={2}
locateFile={locateFile}
>
{shapeData.map(shape => (
<Shape
key={shape.key}
x={shape.x}
y={shape.y}
fill={shape.color}
rotation={rotation}
>
<Rect
x={-SHAPE_SIZE / 2}
y={-SHAPE_SIZE / 2}
width={SHAPE_SIZE}
height={SHAPE_SIZE}
/>
</Shape>
))}
</GlCanvas>
);
}
export default OptimizedCanvas;