fix: hide image during cache resolution to show placeholder
Image is hidden (opacity 0) until the cached URL resolves, preventing broken image icons. The disc placeholder shows through while loading. Adds a subtle 150ms fade-in transition when the image appears.
This commit is contained in:
2 files changed
+14
-5
No files matched your search
@@ -4,8 +4,8 @@
|
|||||||
* Usage:
|
* Usage:
|
||||||
* <img use:cachedSrc={imageUrl} alt="..." />
|
* <img use:cachedSrc={imageUrl} alt="..." />
|
||||||
*
|
*
|
||||||
* Loads the image through the backend cache. Shows nothing until resolved,
|
* Hides the image until the cached URL is resolved, preventing
|
||||||
* then sets the src attribute. Falls back to original URL on error.
|
* broken image icons. The placeholder behind it remains visible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getCachedImageUrl } from '$lib/services/imageCacheService';
|
import { getCachedImageUrl } from '$lib/services/imageCacheService';
|
||||||
@@ -13,21 +13,29 @@ import { getCachedImageUrl } from '$lib/services/imageCacheService';
|
|||||||
export function cachedSrc(node: HTMLImageElement, url: string | undefined) {
|
export function cachedSrc(node: HTMLImageElement, url: string | undefined) {
|
||||||
let currentUrl = url;
|
let currentUrl = url;
|
||||||
|
|
||||||
|
// Hide until resolved so placeholder shows through
|
||||||
|
node.style.opacity = '0';
|
||||||
|
node.removeAttribute('src');
|
||||||
|
|
||||||
async function resolve(imageUrl: string | undefined) {
|
async function resolve(imageUrl: string | undefined) {
|
||||||
if (!imageUrl) {
|
if (!imageUrl) {
|
||||||
node.src = '';
|
node.removeAttribute('src');
|
||||||
|
node.style.opacity = '0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.style.opacity = '0';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resolved = await getCachedImageUrl(imageUrl);
|
const resolved = await getCachedImageUrl(imageUrl);
|
||||||
// Only apply if still the current URL (avoid race conditions)
|
|
||||||
if (imageUrl === currentUrl) {
|
if (imageUrl === currentUrl) {
|
||||||
node.src = resolved;
|
node.src = resolved;
|
||||||
|
node.style.opacity = '1';
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
if (imageUrl === currentUrl) {
|
if (imageUrl === currentUrl) {
|
||||||
node.src = imageUrl; // Fallback to original
|
node.src = imageUrl;
|
||||||
|
node.style.opacity = '1';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
transition: opacity 0.15s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.artwork-placeholder {
|
.artwork-placeholder {
|
||||||
|
|||||||
Reference in new issue
Block a user