fix: image preview/download

This commit is contained in:
Timothy Jaeryang Baek 2025-05-28 15:57:40 +04:00
parent 8a74bdce37
commit 32135a29bb

View File

@ -2,6 +2,9 @@
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte';
import panzoom, { type PanZoom } from 'panzoom'; import panzoom, { type PanZoom } from 'panzoom';
import fileSaver from 'file-saver';
const { saveAs } = fileSaver;
export let show = false; export let show = false;
export let src = ''; export let src = '';
export let alt = ''; export let alt = '';
@ -29,22 +32,6 @@
console.log(instance.getTransform()); console.log(instance.getTransform());
}; };
const downloadImage = (url, filename, prefixName = '') => {
fetch(url)
.then((response) => response.blob())
.then((blob) => {
const objectUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl;
link.download = `${prefixName}${filename}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(objectUrl);
})
.catch((error) => console.error('Error downloading image:', error));
};
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') { if (event.key === 'Escape') {
console.log('Escape'); console.log('Escape');
@ -82,7 +69,7 @@
bind:this={previewElement} bind:this={previewElement}
class="modal fixed top-0 right-0 left-0 bottom-0 bg-black text-white w-full min-h-screen h-screen flex justify-center z-9999 overflow-hidden overscroll-contain" class="modal fixed top-0 right-0 left-0 bottom-0 bg-black text-white w-full min-h-screen h-screen flex justify-center z-9999 overflow-hidden overscroll-contain"
> >
<div class=" absolute left-0 w-full flex justify-between select-none z-10"> <div class=" absolute left-0 w-full flex justify-between select-none z-20">
<div> <div>
<button <button
class=" p-5" class=" p-5"
@ -110,14 +97,38 @@
<div> <div>
<button <button
class=" p-5" class=" p-5 z-999"
on:pointerdown={(e) => { on:click={() => {
e.stopImmediatePropagation(); if (src.startsWith('data:image/')) {
e.preventDefault(); const base64Data = src.split(',')[1];
downloadImage(src, src.substring(src.lastIndexOf('/') + 1), alt); const blob = new Blob([Uint8Array.from(atob(base64Data), (c) => c.charCodeAt(0))], {
}} type: 'image/png'
on:click={(e) => { });
downloadImage(src, src.substring(src.lastIndexOf('/') + 1), alt); saveAs(blob, alt || 'download.png');
return;
} else if (src.startsWith('blob:')) {
// Handle blob URLs
fetch(src)
.then((response) => response.blob())
.then((blob) => {
saveAs(blob, alt || 'download.png');
})
.catch((error) => {
console.error('Error downloading blob:', error);
});
return;
} else if (src.startsWith('http://') || src.startsWith('https://')) {
// Handle remote URLs
fetch(src)
.then((response) => response.blob())
.then((blob) => {
saveAs(blob, alt || 'download.png');
})
.catch((error) => {
console.error('Error downloading remote image:', error);
});
return;
}
}} }}
> >
<svg <svg
@ -136,8 +147,14 @@
</button> </button>
</div> </div>
</div> </div>
<div bind:this={sceneElement} class="flex h-full max-h-full justify-center items-center"> <div class="flex h-full max-h-full justify-center items-center z-0">
<img {src} {alt} class=" mx-auto h-full object-scale-down select-none" draggable="false" /> <img
bind:this={sceneElement}
{src}
{alt}
class=" mx-auto h-full object-scale-down select-none"
draggable="false"
/>
</div> </div>
</div> </div>
{/if} {/if}