Skip to content

Commit

Permalink
Merge pull request #1 from curiousRay/203-zoom-image-improved
Browse files Browse the repository at this point in the history
New method of displaying the full screen image, rather than invoking the browser's API
  • Loading branch information
curiousRay committed Feb 23, 2024
2 parents ef8e1e8 + a3b0f33 commit d8105b9
Showing 1 changed file with 58 additions and 47 deletions.
105 changes: 58 additions & 47 deletions src/components/MDXComponents/ImageZoomable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Fade, IconButton, Tooltip } from "@mui/material";
import { Box, Fade, IconButton} from "@mui/material";

import ZoomInIcon from "@mui/icons-material/ZoomIn";
import ZoomOutIcon from "@mui/icons-material/ZoomOut";
Expand All @@ -10,7 +10,6 @@ import React, {
PropsWithChildren,
useRef,
useState,
useEffect,
} from "react";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";

Expand All @@ -32,56 +31,44 @@ export const ImageZoomable: React.FC<ImageZoomableWrapperProps> = ({ src, alt })
const fullscreen = () => {
if (ImageZoomableRef.current) {
if (isFullscreen) {
document.exitFullscreen();
} else {
ImageZoomableRef.current.requestFullscreen()
.catch((err) => {
console.error(`Error in enabling fullscreen mode: ${err.message}`);
});
}
}
}

useEffect(() => {
window.onresize = () => {
setIsFullScreen((document.fullscreenElement != null) ? true: false);
if (document.fullscreenElement) {

// when entered fullscreen, set image position to flex-centered for better display
const ele = document.fullscreenElement as HTMLElement
ele.style.display = 'flex';
ele.style.alignItems = 'center';
ele.style.justifyContent = 'center';
ele.style.flexFlow = 'column-reverse';
setIsFullScreen(false);
let ele_overlay = ImageZoomableRef.current.getElementsByClassName("zoom-overlay")[0] as HTMLElement;
ele_overlay.style.opacity = "0";
ele_overlay.style.transition = "opacity .15s ease-in-out";

// when entered fullscreen, unset 'position:absolute' zoom button group for better display
const ele2 = ele.querySelector(".ZoomButtonGroup") as HTMLElement;
ele2.style.position = 'unset';
ImageZoomableRef.current.parentElement!.style.height = "unset";
ImageZoomableRef.current.parentElement!.style.border = "none";

} else {
if (ImageZoomableRef.current) {

// exited fullscreen and back to normal position
ImageZoomableRef.current.style.display = 'block';

// exited fullscreen and restore 'position:absolute' of zoom button group
const ele2 = ImageZoomableRef.current.querySelector(".ZoomButtonGroup") as HTMLElement;
ele2.style.position = 'absolute';
}
setIsFullScreen(true);
let ele_overlay = ImageZoomableRef.current.getElementsByClassName("zoom-overlay")[0] as HTMLElement;
ele_overlay.style.opacity = "1";
ele_overlay.style.transition = "opacity .3s ease-in-out";

ImageZoomableRef.current.parentElement!.style.height = "50px";
ImageZoomableRef.current.parentElement!.style.border = "1px grey dashed";

}
}
})
}

return (
<Box
className="ImageZoomableContainer"
ref={ImageZoomableRef}
sx={{
position: (isFullscreen ? "fixed" : "inherit"),
zIndex: (isFullscreen ? "10001" : "inherit")
}}
onMouseEnter={() => {
contextCursor = "grab";
setIsHovered(true);
}}
onMouseLeave={() => {
setIsHovered(false);
if (!isFullscreen) {
setIsHovered(false);
}
}}
onMouseDown={() => {
setIsDragging(true);
Expand All @@ -101,6 +88,7 @@ export const ImageZoomable: React.FC<ImageZoomableWrapperProps> = ({ src, alt })
}, 4000);
}}
>

<TransformWrapper
initialScale={1}
initialPositionX={0}
Expand All @@ -112,34 +100,37 @@ export const ImageZoomable: React.FC<ImageZoomableWrapperProps> = ({ src, alt })
<Box
className="ZoomButtonGroup"
sx={{
position: 'absolute',
float: 'left',
zIndex: 99,
backgroundColor: 'rgb(229,229,229)',
position: (isFullscreen ? "fixed" : "absolute"),
float: "left",
zIndex: (isFullscreen ? 99999 : 99),
backgroundColor: "rgb(229,229,229)",
borderRadius: 18,
marginTop: '.5rem',
marginLeft: '.5rem',
marginTop: ".5rem",
marginLeft: ".5rem",
transform: (isFullscreen ? "translate(-50%,-50%)" : "inherit"),
left: (isFullscreen ? "50%" : "inherit"),
top: (isFullscreen ? "95%" : "inherit")
}}>
<IconButton
aria-label='btn-zoomin'
aria-label="btn-zoomin"
onClick={() => zoomIn()}
>
<ZoomInIcon fontSize={contextIconSize}/>
</IconButton>
<IconButton
aria-label='btn-zoomout'
aria-label="btn-zoomout"
onClick={() => zoomOut()}
>
<ZoomOutIcon fontSize={contextIconSize}/>
</IconButton>
<IconButton
aria-label='btn-zoomreset'
aria-label="btn-zoomreset"
onClick={() => resetTransform()}
>
<AutorenewIcon fontSize={contextIconSize}/>
</IconButton>
<IconButton
aria-label= { isFullscreen ? ('btn-fullscreen-exit') : ('btn-fullscreen') }
aria-label= { isFullscreen ? "btn-fullscreen-exit" : "btn-fullscreen" }
onClick={() => fullscreen()}
>
{ isFullscreen ? (
Expand All @@ -149,12 +140,32 @@ export const ImageZoomable: React.FC<ImageZoomableWrapperProps> = ({ src, alt })
</IconButton>
</Box>
</Fade>
<TransformComponent contentStyle={{ cursor: contextCursor }}>
<TransformComponent
contentStyle={{ cursor: contextCursor }}
wrapperStyle={{
position: (isFullscreen ? "fixed" : "inherit"),
zIndex: (isFullscreen ? "99999" : "inherit"),
left: (isFullscreen ? "50%" : "inherit"),
top: (isFullscreen ? "50%" : "inherit"),
transform: (isFullscreen ? "translate(-50%,-50%) scale(1.6)" : "inherit"),
transition: "transform .3s cubic-bezier(.2,0,.2,1)",
}}>
<img src={src} alt={alt}/>
</TransformComponent>
</React.Fragment>
)}
</TransformWrapper>
<Box
className="zoom-overlay"
sx={{
backgroundColor: "rgba(0,0,0,0.7)",
opacity: "0",
position: "fixed",
zIndex: "99998",
inset: "0",
pointerEvents: "none"
}}
/>
</Box>
);
};

0 comments on commit d8105b9

Please sign in to comment.