Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import { SxProps } from "@mui/material";
import { Dispatch, MouseEvent, SetStateAction, useState } from "react";
type Action = Dispatch<SetStateAction<boolean>> | (() => void) | (() => any);
export const useZoomImage = (
setIsZooming?: Action,
{ safeElements }: { safeElements?: string | Array<string> } = {},
) => {
const [enableZoom, setEnableZoom] = useState<boolean>(false);
const [zoom, setZoom] = useState<number>(1);
const [x, setX] = useState<number>(0);
const [y, setY] = useState<number>(0);
const zoomer = (event: MouseEvent<HTMLDivElement>) => {
// Get the dimensions and position of the image container
const { left, top, width, height } =
event.currentTarget.getBoundingClientRect();
// Horizontal and vertical offset of the mouse pointer from the container's top-left corner
const offsetX = event.clientX - left;
const offsetY = event.clientY - top;
// Relative position of the mouse pointer within the container
setX(offsetX / width);
setY(offsetY / height);
setZoom(3);
// Trigger action if it exists
setIsZooming && setIsZooming(true);
};
const handleClick = (event: MouseEvent<HTMLDivElement>) => {
setEnableZoom((v) => !v);
if (zoom === 1) {
zoomer(event);
} else {
setZoom(1);
setIsZooming && setIsZooming(false);
}
};
const handleMouseMove = (event: MouseEvent<HTMLDivElement>) => {
zoomer(event);
};
const handleMouseLeave = (e: MouseEvent) => {
const el = e.relatedTarget as HTMLDivElement;
if (el.id && safeElements?.includes(el.id)) return;
setZoom(1);
setIsZooming && setIsZooming(false), setEnableZoom(false);
};
const parentElZoomStyleProps: SxProps = {
position: "relative",
overflow: "hidden",
cursor: zoom == 1 ? "zoom-in" : "zoom-out",
};
const zoomedElStyleProps: SxProps = {
position: "absolute",
top: 0,
left: 0,
maxWidth: "initial",
transform: `scale(${zoom})`,
// Set the transform origin to the mouse position within the container
// Multiplication by 100 is to convert from decimal to percentage
transformOrigin: `${x * 100}% ${y * 100}%`,
// Apply a smooth transition effect to the transformation
transition: "transform 0.3s ease",
};
return {
parentElZoomStyleProps,
zoomedElStyleProps,
handleMouseLeave: enableZoom ? handleMouseLeave : undefined,
handleMouseMove: enableZoom ? handleMouseMove : undefined,
handleClick,
};
};
|