Convert zoom controls into hook
This commit is contained in:
parent
5139abcdba
commit
2195379b74
@ -23,6 +23,7 @@ import ShareModals from '@/share/ShareModals';
|
|||||||
|
|
||||||
import '../site/globals.css';
|
import '../site/globals.css';
|
||||||
import '../site/sonner.css';
|
import '../site/sonner.css';
|
||||||
|
import '../site/viewerjs.css';
|
||||||
|
|
||||||
const ibmPlexMono = IBM_Plex_Mono({
|
const ibmPlexMono = IBM_Plex_Mono({
|
||||||
subsets: ['latin'],
|
subsets: ['latin'],
|
||||||
|
|||||||
@ -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>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
29
src/components/image/useImageZoomControls.ts
Normal file
29
src/components/image/useImageZoomControls.ts
Normal 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]);
|
||||||
|
}
|
||||||
@ -113,7 +113,7 @@ export default function PhotoDetailPage({
|
|||||||
shouldShareSimulation={simulation !== undefined}
|
shouldShareSimulation={simulation !== undefined}
|
||||||
shouldScrollOnShare={false}
|
shouldScrollOnShare={false}
|
||||||
includeFavoriteInAdminMenu={includeFavoriteInAdminMenu}
|
includeFavoriteInAdminMenu={includeFavoriteInAdminMenu}
|
||||||
enableImageActions={ZOOM_CONTROLS_ENABLED}
|
shouldShowZoomControls={ZOOM_CONTROLS_ENABLED}
|
||||||
/>,
|
/>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import { useRef } from 'react';
|
|||||||
import useOnVisible from '@/utility/useOnVisible';
|
import useOnVisible from '@/utility/useOnVisible';
|
||||||
import PhotoDate from './PhotoDate';
|
import PhotoDate from './PhotoDate';
|
||||||
import { useAppState } from '@/state/AppState';
|
import { useAppState } from '@/state/AppState';
|
||||||
import ImageZoomControls from '@/components/image/ImageZoomControls';
|
import useImageZoomControls from '@/components/image/useImageZoomControls';
|
||||||
|
|
||||||
export default function PhotoLarge({
|
export default function PhotoLarge({
|
||||||
photo,
|
photo,
|
||||||
@ -55,9 +55,9 @@ export default function PhotoLarge({
|
|||||||
shouldShareCamera,
|
shouldShareCamera,
|
||||||
shouldShareSimulation,
|
shouldShareSimulation,
|
||||||
shouldShareFocalLength,
|
shouldShareFocalLength,
|
||||||
|
shouldShowZoomControls,
|
||||||
includeFavoriteInAdminMenu,
|
includeFavoriteInAdminMenu,
|
||||||
onVisible,
|
onVisible,
|
||||||
enableImageActions = false,
|
|
||||||
}: {
|
}: {
|
||||||
photo: Photo
|
photo: Photo
|
||||||
className?: string
|
className?: string
|
||||||
@ -76,11 +76,12 @@ export default function PhotoLarge({
|
|||||||
shouldShareSimulation?: boolean
|
shouldShareSimulation?: boolean
|
||||||
shouldShareFocalLength?: boolean
|
shouldShareFocalLength?: boolean
|
||||||
shouldScrollOnShare?: boolean
|
shouldScrollOnShare?: boolean
|
||||||
|
shouldShowZoomControls?: boolean
|
||||||
includeFavoriteInAdminMenu?: boolean
|
includeFavoriteInAdminMenu?: boolean
|
||||||
onVisible?: () => void
|
onVisible?: () => void
|
||||||
enableImageActions?: boolean
|
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const refZoomControls = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const tags = sortTags(photo.tags, primaryTag);
|
const tags = sortTags(photo.tags, primaryTag);
|
||||||
|
|
||||||
@ -92,6 +93,8 @@ export default function PhotoLarge({
|
|||||||
|
|
||||||
useOnVisible(ref, onVisible);
|
useOnVisible(ref, onVisible);
|
||||||
|
|
||||||
|
useImageZoomControls(refZoomControls, shouldShowZoomControls);
|
||||||
|
|
||||||
const { arePhotosMatted, isUserSignedIn } = useAppState();
|
const { arePhotosMatted, isUserSignedIn } = useAppState();
|
||||||
|
|
||||||
const hasTitle =
|
const hasTitle =
|
||||||
@ -146,9 +149,9 @@ export default function PhotoLarge({
|
|||||||
arePhotosMatted && 'h-[90%]',
|
arePhotosMatted && 'h-[90%]',
|
||||||
arePhotosMatted && matteContentWidthForAspectRatio(),
|
arePhotosMatted && matteContentWidthForAspectRatio(),
|
||||||
)}>
|
)}>
|
||||||
<ImageZoomControls
|
<div
|
||||||
enableImageActions={enableImageActions}
|
ref={refZoomControls}
|
||||||
className="flex relative items-center justify-center h-full"
|
className={clsx(shouldShowZoomControls && 'cursor-zoom-in')}
|
||||||
>
|
>
|
||||||
<ImageLarge
|
<ImageLarge
|
||||||
className={clsx(arePhotosMatted && 'h-full')}
|
className={clsx(arePhotosMatted && 'h-full')}
|
||||||
@ -161,7 +164,7 @@ export default function PhotoLarge({
|
|||||||
blurCompatibilityMode={doesPhotoNeedBlurCompatibility(photo)}
|
blurCompatibilityMode={doesPhotoNeedBlurCompatibility(photo)}
|
||||||
priority={priority}
|
priority={priority}
|
||||||
/>
|
/>
|
||||||
</ImageZoomControls>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>}
|
</Link>}
|
||||||
contentSide={
|
contentSide={
|
||||||
|
|||||||
16
src/site/viewerjs.css
Normal file
16
src/site/viewerjs.css
Normal 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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user