ui(player): soften vinyl-stage halo, transparent-bg album placeholder, crossfade artwork swaps
Lint & Test / test (push) Successful in 1m50s

- vinyl-stage background fades to transparent (matches fullscreen Listening Room) — no more rectangular dark card around the sleeve+disc composition
- album-art placeholder SVG drops the opaque #282828 backdrop in favour of a translucent disc glyph so the sleeve cardstock shows through before the first artwork load
- new swapArtworkSrc helper retriggers the .is-swapping keyframes so artwork changes crossfade instead of popping
This commit is contained in:
2026-04-25 15:22:08 +03:00
parent 59840a1190
commit 4c93bfb8c1
3 changed files with 61 additions and 29 deletions
+15 -3
View File
@@ -613,6 +613,18 @@ export function setupProgressDrag(bar, fill) {
});
}
// Replace the album-art src and replay the .is-swapping CSS animation
// so the new artwork crossfades in instead of popping. Re-toggling the
// class across rAF restarts the keyframes even if it was already on.
function swapArtworkSrc(imgEl, newSrc) {
if (!imgEl) return;
if (imgEl.src === newSrc) return;
imgEl.classList.remove('is-swapping');
void imgEl.offsetWidth;
imgEl.src = newSrc;
imgEl.classList.add('is-swapping');
}
export function updateUI(status) {
setLastStatus(status);
@@ -639,7 +651,7 @@ export function updateUI(status) {
if (artworkKey !== lastArtworkKey) {
lastArtworkKey = artworkKey;
const placeholderArt = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Crect fill='%23282828' width='300' height='300'/%3E%3Cpath fill='%236a6a6a' d='M150 80c-38.66 0-70 31.34-70 70s31.34 70 70 70 70-31.34 70-70-31.34-70-70-70zm0 20c27.614 0 50 22.386 50 50s-22.386 50-50 50-50-22.386-50-50 22.386-50 50-50zm0 30a20 20 0 100 40 20 20 0 000-40z'/%3E%3C/svg%3E";
const placeholderArt = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Cpath fill='%236a6a6a' opacity='0.35' d='M150 80c-38.66 0-70 31.34-70 70s31.34 70 70 70 70-31.34 70-70-31.34-70-70-70zm0 20c27.614 0 50 22.386 50 50s-22.386 50-50 50-50-22.386-50-50 22.386-50 50-50zm0 30a20 20 0 100 40 20 20 0 000-40z'/%3E%3C/svg%3E";
const placeholderGlow = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'%3E%3Crect fill='%23282828' width='300' height='300'/%3E%3C/svg%3E";
if (artworkSource) {
fetch(`/api/media/artwork?_=${Date.now()}`, {
@@ -651,7 +663,7 @@ export function updateUI(status) {
const oldBlobUrl = currentArtworkBlobUrl;
const url = URL.createObjectURL(blob);
currentArtworkBlobUrl = url;
dom.albumArt.src = url;
swapArtworkSrc(dom.albumArt, url);
dom.miniAlbumArt.src = url;
if (dom.albumArtGlow) dom.albumArtGlow.src = url;
if (oldBlobUrl) setTimeout(() => URL.revokeObjectURL(oldBlobUrl), 1000);
@@ -662,7 +674,7 @@ export function updateUI(status) {
URL.revokeObjectURL(currentArtworkBlobUrl);
currentArtworkBlobUrl = null;
}
dom.albumArt.src = placeholderArt;
swapArtworkSrc(dom.albumArt, placeholderArt);
dom.miniAlbumArt.src = placeholderArt;
if (dom.albumArtGlow) dom.albumArtGlow.src = placeholderGlow;
}