import { useEffect } from "react"; export function useHiDPICanvas( imgRef: React.RefObject, canvasRef: React.RefObject ) { const sync = () => { const img = imgRef.current, cvs = canvasRef.current; if (!img || !cvs) return; const dpr = window.devicePixelRatio || 1; const w = img.clientWidth || img.naturalWidth || 0; const h = img.clientHeight || img.naturalHeight || 0; // CSS size cvs.style.width = `${w}px`; cvs.style.height = `${h}px`; // backing store size (scaled for HiDPI) const W = Math.max(1, Math.round(w * dpr)); const H = Math.max(1, Math.round(h * dpr)); if (cvs.width !== W || cvs.height !== H) { cvs.width = W; cvs.height = H; const ctx = cvs.getContext("2d"); if (ctx) ctx.setTransform(dpr, 0, 0, dpr, 0, 0); // draw in CSS px } }; useEffect(() => { const ro = new ResizeObserver(sync); // reacts to image size changes if (imgRef.current) ro.observe(imgRef.current); const onResize = () => sync(); window.addEventListener("resize", onResize); return () => { ro.disconnect(); window.removeEventListener("resize", onResize); }; }, []); // eslint-disable-line react-hooks/exhaustive-deps return { sync }; }