mirror of
https://github.com/immich-app/immich.git
synced 2025-01-21 00:52:43 -05:00
feat(web): load original image when zooming (#4040)
* feat(web): change max zoom from 4 to 10 * feat(web): load original image when zooming
This commit is contained in:
parent
52d0c5fc73
commit
bf3b38a7f2
2 changed files with 24 additions and 5 deletions
|
@ -6,12 +6,14 @@
|
||||||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||||
import { useZoomImageWheel } from '@zoom-image/svelte';
|
import { useZoomImageWheel } from '@zoom-image/svelte';
|
||||||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||||
|
import { isWebCompatibleImage } from '$lib/utils/asset-utils';
|
||||||
|
|
||||||
export let asset: AssetResponseDto;
|
export let asset: AssetResponseDto;
|
||||||
export let element: HTMLDivElement | undefined = undefined;
|
export let element: HTMLDivElement | undefined = undefined;
|
||||||
|
|
||||||
let imgElement: HTMLDivElement;
|
let imgElement: HTMLDivElement;
|
||||||
let assetData: string;
|
let assetData: string;
|
||||||
|
let hasZoomed = false;
|
||||||
let copyImageToClipboard: (src: string) => Promise<Blob>;
|
let copyImageToClipboard: (src: string) => Promise<Blob>;
|
||||||
let canCopyImagesToClipboard: () => boolean;
|
let canCopyImagesToClipboard: () => boolean;
|
||||||
|
|
||||||
|
@ -23,10 +25,10 @@
|
||||||
canCopyImagesToClipboard = module.canCopyImagesToClipboard;
|
canCopyImagesToClipboard = module.canCopyImagesToClipboard;
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadAssetData = async () => {
|
const loadAssetData = async ({ loadOriginal }: { loadOriginal: boolean }) => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.assetApi.serveFile(
|
const { data } = await api.assetApi.serveFile(
|
||||||
{ id: asset.id, isThumb: false, isWeb: true, key: api.getKey() },
|
{ id: asset.id, isThumb: false, isWeb: !loadOriginal, key: api.getKey() },
|
||||||
{
|
{
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
},
|
},
|
||||||
|
@ -37,7 +39,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
assetData = URL.createObjectURL(data);
|
assetData = URL.createObjectURL(data);
|
||||||
return assetData;
|
|
||||||
} catch {
|
} catch {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
@ -87,10 +88,16 @@
|
||||||
|
|
||||||
zoomImageWheelState.subscribe((state) => {
|
zoomImageWheelState.subscribe((state) => {
|
||||||
photoZoomState.set(state);
|
photoZoomState.set(state);
|
||||||
|
|
||||||
|
if (state.currentZoom > 1 && isWebCompatibleImage(asset) && !hasZoomed) {
|
||||||
|
hasZoomed = true;
|
||||||
|
loadAssetData({ loadOriginal: true });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: if (imgElement) {
|
$: if (imgElement) {
|
||||||
createZoomImageWheel(imgElement, {
|
createZoomImageWheel(imgElement, {
|
||||||
|
maxZoom: 10,
|
||||||
wheelZoomRatio: 0.2,
|
wheelZoomRatio: 0.2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -103,9 +110,9 @@
|
||||||
transition:fade={{ duration: 150 }}
|
transition:fade={{ duration: 150 }}
|
||||||
class="flex h-full select-none place-content-center place-items-center"
|
class="flex h-full select-none place-content-center place-items-center"
|
||||||
>
|
>
|
||||||
{#await loadAssetData()}
|
{#await loadAssetData({ loadOriginal: false })}
|
||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
{:then assetData}
|
{:then}
|
||||||
<div bind:this={imgElement} class="h-full w-full">
|
<div bind:this={imgElement} class="h-full w-full">
|
||||||
<img
|
<img
|
||||||
transition:fade={{ duration: 150 }}
|
transition:fade={{ duration: 150 }}
|
||||||
|
|
|
@ -173,3 +173,15 @@ export function getAssetRatio(asset: AssetResponseDto) {
|
||||||
}
|
}
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// list of supported image extensions from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types excluding svg
|
||||||
|
const supportedImageExtensions = new Set(['apng', 'avif', 'gif', 'jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp', 'png', 'webp']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the asset is an image supported by web browsers, false otherwise
|
||||||
|
*/
|
||||||
|
export function isWebCompatibleImage(asset: AssetResponseDto): boolean {
|
||||||
|
const imgExtension = getFilenameExtension(asset.originalPath);
|
||||||
|
|
||||||
|
return supportedImageExtensions.has(imgExtension);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue