mirror of
https://github.com/immich-app/immich.git
synced 2026-03-12 21:42:54 -07:00
Compare commits
1 Commits
push-lvmzu
...
push-wvnmq
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fe63b70a6 |
@@ -9,14 +9,15 @@ export const zoomImageAction = (node: HTMLElement, options?: { disabled?: boolea
|
||||
zoomInstance.subscribe(({ state }) => assetViewerManager.onZoomChange(state)),
|
||||
];
|
||||
|
||||
const stopIfDisabled = (event: Event) => {
|
||||
const onInteractionStart = (event: Event) => {
|
||||
if (options?.disabled) {
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
assetViewerManager.cancelZoomAnimation();
|
||||
};
|
||||
|
||||
node.addEventListener('wheel', stopIfDisabled, { capture: true });
|
||||
node.addEventListener('pointerdown', stopIfDisabled, { capture: true });
|
||||
node.addEventListener('wheel', onInteractionStart, { capture: true });
|
||||
node.addEventListener('pointerdown', onInteractionStart, { capture: true });
|
||||
|
||||
node.style.overflow = 'visible';
|
||||
return {
|
||||
@@ -27,8 +28,8 @@ export const zoomImageAction = (node: HTMLElement, options?: { disabled?: boolea
|
||||
for (const unsubscribe of unsubscribes) {
|
||||
unsubscribe();
|
||||
}
|
||||
node.removeEventListener('wheel', stopIfDisabled, { capture: true });
|
||||
node.removeEventListener('pointerdown', stopIfDisabled, { capture: true });
|
||||
node.removeEventListener('wheel', onInteractionStart, { capture: true });
|
||||
node.removeEventListener('pointerdown', onInteractionStart, { capture: true });
|
||||
zoomInstance.cleanup();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -103,7 +103,8 @@
|
||||
};
|
||||
|
||||
const onZoom = () => {
|
||||
assetViewerManager.zoom = assetViewerManager.zoom > 1 ? 1 : 2;
|
||||
const targetZoom = assetViewerManager.zoom > 1 ? 1 : 2;
|
||||
assetViewerManager.animatedZoom(targetZoom);
|
||||
};
|
||||
|
||||
const onPlaySlideshow = () => ($slideshowState = SlideshowState.PlaySlideshow);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { canCopyImageToClipboard } from '$lib/utils/asset-utils';
|
||||
import { BaseEventManager } from '$lib/utils/base-event-manager.svelte';
|
||||
import { PersistedLocalStorage } from '$lib/utils/persisted';
|
||||
import type { ZoomImageWheelState } from '@zoom-image/core';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
|
||||
const isShowDetailPanel = new PersistedLocalStorage<boolean>('asset-viewer-state', false);
|
||||
|
||||
@@ -21,6 +22,7 @@ export type Events = {
|
||||
|
||||
export class AssetViewerManager extends BaseEventManager<Events> {
|
||||
#zoomState = $state(createDefaultZoomState());
|
||||
#animationFrameId: number | null = null;
|
||||
|
||||
imgRef = $state<HTMLImageElement | undefined>();
|
||||
isShowActivityPanel = $state(false);
|
||||
@@ -45,6 +47,7 @@ export class AssetViewerManager extends BaseEventManager<Events> {
|
||||
}
|
||||
|
||||
set zoom(zoom: number) {
|
||||
this.cancelZoomAnimation();
|
||||
this.zoomState = { ...this.zoomState, currentZoom: zoom };
|
||||
}
|
||||
|
||||
@@ -69,7 +72,35 @@ export class AssetViewerManager extends BaseEventManager<Events> {
|
||||
this.#zoomState = state;
|
||||
}
|
||||
|
||||
cancelZoomAnimation() {
|
||||
if (this.#animationFrameId !== null) {
|
||||
cancelAnimationFrame(this.#animationFrameId);
|
||||
this.#animationFrameId = null;
|
||||
}
|
||||
}
|
||||
|
||||
animatedZoom(targetZoom: number, duration = 300) {
|
||||
this.cancelZoomAnimation();
|
||||
|
||||
const startZoom = this.#zoomState.currentZoom;
|
||||
const startTime = performance.now();
|
||||
|
||||
const frame = (currentTime: number) => {
|
||||
const elapsed = currentTime - startTime;
|
||||
const linearProgress = Math.min(elapsed / duration, 1);
|
||||
const easedProgress = cubicOut(linearProgress);
|
||||
const interpolatedZoom = startZoom + (targetZoom - startZoom) * easedProgress;
|
||||
|
||||
this.zoomState = { ...this.#zoomState, currentZoom: interpolatedZoom };
|
||||
|
||||
this.#animationFrameId = linearProgress < 1 ? requestAnimationFrame(frame) : null;
|
||||
};
|
||||
|
||||
this.#animationFrameId = requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
resetZoomState() {
|
||||
this.cancelZoomAnimation();
|
||||
this.zoomState = createDefaultZoomState();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user