Files
Mav-Mobile-UI/src/hooks/useHiDPICanvas.ts
2025-08-20 08:27:05 +01:00

44 lines
1.3 KiB
TypeScript

import { useEffect } from "react";
export function useHiDPICanvas(
imgRef: React.RefObject<HTMLImageElement | null>,
canvasRef: React.RefObject<HTMLCanvasElement | null>
) {
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 };
}