DvdScreensaver.tsx
import React from "react";export default function DvdScreensaver() { const ref = React.useRef<HTMLCanvasElement>(null); const [speed, setSpeed] = React.useState(100); React.useEffect(() => { if (!ref.current) return; const ctx = ref.current.getContext("2d"); let requestId: number; let secondsPassed = 0; let oldTimeStamp = 0; let x = 0.0; let y = 0.0; let dx = speed; let dy = speed; let color = `rgb(${Math.random() * 256}, ${Math.random() * 256}, ${ Math.random() * 256 })`; loop(Date.now()); function loop(timestamp: number) { secondsPassed = (timestamp - oldTimeStamp) / 1000; secondsPassed = Math.min(secondsPassed, 0.1); if (secondsPassed < 0) secondsPassed = 0; oldTimeStamp = timestamp; update(secondsPassed); draw(); requestId = requestAnimationFrame(loop); } function update(secondsPassed: number) { x += dx * secondsPassed; y += dy * secondsPassed; if (x + 100 > 1000 || x < 0) { dx *= -1; color = `rgb(${Math.random() * 256}, ${Math.random() * 256}, ${ Math.random() * 256 })`; } if (y + 100 > 500 || y < 0) { dy *= -1; color = `rgb(${Math.random() * 256}, ${Math.random() * 256}, ${ Math.random() * 256 })`; } } function draw() { if (!ctx) return; ctx.clearRect(0, 0, 1000, 500); ctx.fillStyle = color; ctx.fillRect(x, y, 100, 100); } return () => { cancelAnimationFrame(requestId); }; }, [speed]); return ( <> <canvas width={1000} height={500} ref={ref} className="border"></canvas> <label> Speed <input value={speed} onChange={(e) => setSpeed(Number(e.target.value))} type="range" max={1000} step={100} min={0} /> </label> </> );}