MediaQuickview: add recenter
All checks were successful
/ checkpr (pull_request) Successful in 1m22s

This commit is contained in:
thislight 2024-12-07 21:31:14 +08:00
parent 148047db17
commit dfaecf3b6b
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E
2 changed files with 61 additions and 7 deletions

View file

@ -47,8 +47,6 @@
max-width: 100vw; max-width: 100vw;
max-height: 100vh; max-height: 100vh;
contain: strict; contain: strict;
display: grid;
place-items: center;
cursor: grab; cursor: grab;

View file

@ -56,19 +56,39 @@ export function createMediaQuickview() {
return createCallback(renderIsolateMediaQuickview); return createCallback(renderIsolateMediaQuickview);
} }
type VisualMediaMeta = {
width: number;
height: number;
};
function ImagePage(props: { function ImagePage(props: {
src: string; src: string;
alt?: string; alt?: string;
scale: number; scale: number;
offsetX: number; offsetX: number;
offsetY: number; offsetY: number;
onMetadata?(metadata: VisualMediaMeta): void;
}) { }) {
const [loaded, setLoaded] = createSignal(false);
return ( return (
<img <img
onLoad={({ currentTarget }) => {
const { naturalHeight, naturalWidth } = currentTarget;
props.onMetadata?.({
width: naturalWidth,
height: naturalHeight,
});
setLoaded(true);
}}
src={props.src} src={props.src}
alt={props.alt} alt={props.alt}
style={{ style={{
transform: `scale(${props.scale}) translateX(${-props.offsetX}px) translateY(${-props.offsetY}px)`, transform: `scale(${props.scale}) translateX(${-props.offsetX}px) translateY(${-props.offsetY}px)`,
opacity: loaded() ? 1 : 0,
}} }}
></img> ></img>
); );
@ -88,10 +108,6 @@ export type MediaQuickviewProps = {
onClose?(): void; onClose?(): void;
}; };
function clamp<T extends number>(value: T, min: T, max: T) {
return Math.max(Math.min(value, max), min);
}
const MediaQuickview: Component<MediaQuickviewProps> = (props) => { const MediaQuickview: Component<MediaQuickviewProps> = (props) => {
let root: HTMLDialogElement; let root: HTMLDialogElement;
@ -126,6 +142,11 @@ const MediaQuickview: Component<MediaQuickviewProps> = (props) => {
* positive = the top edge move towards top * positive = the top edge move towards top
*/ */
offsetY: number; offsetY: number;
size?: {
width: number;
height: number;
};
}[], }[],
); );
@ -202,6 +223,40 @@ const MediaQuickview: Component<MediaQuickviewProps> = (props) => {
setIsMoving(false); 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 ( return (
<dialog <dialog
ref={(e) => { ref={(e) => {
@ -254,6 +309,7 @@ const MediaQuickview: Component<MediaQuickviewProps> = (props) => {
<Switch> <Switch>
<Match when={item().cat === "image"}> <Match when={item().cat === "image"}>
<ImagePage <ImagePage
onMetadata={(m) => onMetadata(index, m)}
src={item().src} src={item().src}
alt={item().alt} alt={item().alt}
scale={transformationGetOrSetDefault(index).scale} scale={transformationGetOrSetDefault(index).scale}