From a720f5d9c42042d376b146efe361c751a6cc89a6 Mon Sep 17 00:00:00 2001 From: thislight Date: Sat, 7 Dec 2024 21:31:14 +0800 Subject: [PATCH] MediaQuickview: add recenter --- src/platform/MediaQuickview.css | 2 - src/platform/MediaQuickview.tsx | 66 ++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/platform/MediaQuickview.css b/src/platform/MediaQuickview.css index 0161fcf..3ad798c 100644 --- a/src/platform/MediaQuickview.css +++ b/src/platform/MediaQuickview.css @@ -47,8 +47,6 @@ max-width: 100vw; max-height: 100vh; contain: strict; - display: grid; - place-items: center; cursor: grab; diff --git a/src/platform/MediaQuickview.tsx b/src/platform/MediaQuickview.tsx index e06cf0c..c4b2cde 100644 --- a/src/platform/MediaQuickview.tsx +++ b/src/platform/MediaQuickview.tsx @@ -56,19 +56,39 @@ export function createMediaQuickview() { return createCallback(renderIsolateMediaQuickview); } +type VisualMediaMeta = { + width: number; + height: number; +}; + function ImagePage(props: { src: string; alt?: string; scale: number; offsetX: number; offsetY: number; + + onMetadata?(metadata: VisualMediaMeta): void; }) { + const [loaded, setLoaded] = createSignal(false); + return ( { + const { naturalHeight, naturalWidth } = currentTarget; + + props.onMetadata?.({ + width: naturalWidth, + height: naturalHeight, + }); + + setLoaded(true); + }} src={props.src} alt={props.alt} style={{ transform: `scale(${props.scale}) translateX(${-props.offsetX}px) translateY(${-props.offsetY}px)`, + opacity: loaded() ? 1 : 0, }} > ); @@ -88,10 +108,6 @@ export type MediaQuickviewProps = { onClose?(): void; }; -function clamp(value: T, min: T, max: T) { - return Math.max(Math.min(value, max), min); -} - const MediaQuickview: Component = (props) => { let root: HTMLDialogElement; @@ -126,6 +142,11 @@ const MediaQuickview: Component = (props) => { * positive = the top edge move towards top */ offsetY: number; + + size?: { + width: number; + height: number; + }; }[], ); @@ -185,7 +206,7 @@ const MediaQuickview: Component = (props) => { return; } const dx = movOriginX - event.clientX; - const dy = movOriginY - event.clientY ; + const dy = movOriginY - event.clientY; setTransformations(index, ({ offsetX, offsetY }) => { return { @@ -202,6 +223,40 @@ const MediaQuickview: Component = (props) => { setIsMoving(false); }; + const recenter = (index: number) => { + const sz = transformations[index].size; + if (!sz) return; + const { width, height } = sz; + + const xscale = Math.min(window.innerWidth / width, 1); + const yscale = Math.min(window.innerHeight / height, 1); + + const finalScale = Math.min(xscale, yscale); + + const nheight = height * finalScale; + const top = (window.innerHeight - nheight) / 2; + + const nwidth = width * finalScale; + const left = (window.innerWidth - nwidth) / 2; + + setTransformations(index, { + scale: finalScale, + offsetX: -left, + offsetY: -top, + }); + }; + + const onMetadata = (index: number, { width, height }: VisualMediaMeta) => { + setTransformations(index, { + size: { + width, + height, + }, + }); + + recenter(index); + }; + return ( { @@ -254,6 +309,7 @@ const MediaQuickview: Component = (props) => { onMetadata(index, m)} src={item().src} alt={item().alt} scale={transformationGetOrSetDefault(index).scale}