Convert zoom controls into hook

This commit is contained in:
Sam Becker 2025-01-26 10:24:00 -06:00
parent 5139abcdba
commit 2195379b74
6 changed files with 58 additions and 77 deletions

View File

@ -23,6 +23,7 @@ import ShareModals from '@/share/ShareModals';
import '../site/globals.css';
import '../site/sonner.css';
import '../site/viewerjs.css';
const ibmPlexMono = IBM_Plex_Mono({
subsets: ['latin'],

View File

@ -1,68 +0,0 @@
import { useEffect, useRef } from 'react';
import Viewer from 'viewerjs';
import 'viewerjs/dist/viewer.css';
import { clsx } from 'clsx/lite';
import FullscreenButton from '../FullscreenButton';
export default function ImageZoomControls({
children,
enableImageActions = false,
className,
}: {
children: React.ReactNode;
enableImageActions?: boolean;
className?: string;
}) {
const containerRef = useRef<HTMLDivElement>(null);
const viewerRef = useRef<Viewer | null>(null);
useEffect(() => {
if (containerRef.current && enableImageActions) {
viewerRef.current = new Viewer(containerRef.current, {
inline: false,
button: true,
navbar: false,
title: false,
toolbar: {
zoomIn: 1,
zoomOut: 1,
reset: 1,
tooltip: 1,
},
});
return () => {
viewerRef.current?.destroy();
};
}
}, [enableImageActions]);
return (
<>
<style jsx global>{`
.viewer-canvas {
background-color: black !important;
}
.viewer-reset::before {
content: '1:1';
font-size: 13px;
font-weight: 600;
color: #fff;
display: inline-block;
position: relative;
bottom: -9px;
letter-spacing: -2px;
background-image: none;
}
`}</style>
<div
className={clsx(className, enableImageActions && 'cursor-zoom-in')}
ref={containerRef}
>
{children}
{enableImageActions && (
<FullscreenButton imageRef={containerRef} />
)}
</div>
</>
);
}

View File

@ -0,0 +1,29 @@
import { RefObject, useEffect, useRef } from 'react';
import Viewer from 'viewerjs';
export default function useImageZoomControls(
imageRef: RefObject<HTMLDivElement | null>,
isEnabled?: boolean,
) {
const viewerRef = useRef<Viewer | null>(null);
useEffect(() => {
if (imageRef.current && isEnabled) {
viewerRef.current = new Viewer(imageRef.current, {
inline: false,
button: true,
navbar: false,
title: false,
toolbar: {
zoomIn: 1,
zoomOut: 1,
reset: 1,
tooltip: 1,
},
});
return () => {
viewerRef.current?.destroy();
};
}
}, [imageRef, isEnabled]);
}

View File

@ -113,7 +113,7 @@ export default function PhotoDetailPage({
shouldShareSimulation={simulation !== undefined}
shouldScrollOnShare={false}
includeFavoriteInAdminMenu={includeFavoriteInAdminMenu}
enableImageActions={ZOOM_CONTROLS_ENABLED}
shouldShowZoomControls={ZOOM_CONTROLS_ENABLED}
/>,
]}
/>

View File

@ -36,7 +36,7 @@ import { useRef } from 'react';
import useOnVisible from '@/utility/useOnVisible';
import PhotoDate from './PhotoDate';
import { useAppState } from '@/state/AppState';
import ImageZoomControls from '@/components/image/ImageZoomControls';
import useImageZoomControls from '@/components/image/useImageZoomControls';
export default function PhotoLarge({
photo,
@ -55,9 +55,9 @@ export default function PhotoLarge({
shouldShareCamera,
shouldShareSimulation,
shouldShareFocalLength,
shouldShowZoomControls,
includeFavoriteInAdminMenu,
onVisible,
enableImageActions = false,
}: {
photo: Photo
className?: string
@ -76,11 +76,12 @@ export default function PhotoLarge({
shouldShareSimulation?: boolean
shouldShareFocalLength?: boolean
shouldScrollOnShare?: boolean
shouldShowZoomControls?: boolean
includeFavoriteInAdminMenu?: boolean
onVisible?: () => void
enableImageActions?: boolean
}) {
const ref = useRef<HTMLDivElement>(null);
const refZoomControls = useRef<HTMLDivElement>(null);
const tags = sortTags(photo.tags, primaryTag);
@ -92,6 +93,8 @@ export default function PhotoLarge({
useOnVisible(ref, onVisible);
useImageZoomControls(refZoomControls, shouldShowZoomControls);
const { arePhotosMatted, isUserSignedIn } = useAppState();
const hasTitle =
@ -146,14 +149,14 @@ export default function PhotoLarge({
arePhotosMatted && 'h-[90%]',
arePhotosMatted && matteContentWidthForAspectRatio(),
)}>
<ImageZoomControls
enableImageActions={enableImageActions}
className="flex relative items-center justify-center h-full"
<div
ref={refZoomControls}
className={clsx(shouldShowZoomControls && 'cursor-zoom-in')}
>
<ImageLarge
className={clsx(arePhotosMatted && 'h-full')}
imgClassName={clsx(arePhotosMatted &&
'object-contain w-full h-full')}
'object-contain w-full h-full')}
alt={altTextForPhoto(photo)}
src={photo.url}
aspectRatio={photo.aspectRatio}
@ -161,7 +164,7 @@ export default function PhotoLarge({
blurCompatibilityMode={doesPhotoNeedBlurCompatibility(photo)}
priority={priority}
/>
</ImageZoomControls>
</div>
</div>
</Link>}
contentSide={

16
src/site/viewerjs.css Normal file
View File

@ -0,0 +1,16 @@
@import 'viewerjs/dist/viewer.css';
.viewer-canvas {
background-color: black !important;
}
.viewer-reset::before {
content: '1:1';
font-size: 13px;
font-weight: 600;
color: #fff;
display: inline-block;
position: relative;
bottom: -9px;
letter-spacing: -2px;
background-image: none;
}