type Viewport = { width: number; height: number; pixelRatio: number; }; const settings = { frameRate: 60, easing: 0.085, threshold: 0.001 } as const; const clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value)); function createRenderer(canvas: HTMLCanvasElement) { const context = canvas.getContext("2d"); if (!context) throw new Error("Canvas unavailable"); let viewport: Viewport; let frameId = 0; let elapsed = 0; const resize = () => { const bounds = canvas.getBoundingClientRect(); const ratio = clamp(devicePixelRatio, 1, 2); viewport = { width: bounds.width, height: bounds.height, pixelRatio: ratio }; canvas.width = bounds.width * ratio; canvas.height = bounds.height * ratio; context.setTransform(ratio, 0, 0, ratio, 0, 0); }; const render = (time: number) => { elapsed = time * 0.001; context.clearRect(0, 0, viewport.width, viewport.height); frameId = requestAnimationFrame(render); }; const observer = new ResizeObserver(resize); observer.observe(canvas); resize(); frameId = requestAnimationFrame(render); return () => { observer.disconnect(); cancelAnimationFrame(frameId); }; } export { createRenderer, settings };