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>
</>
);
}