fix: hero non-blocking — reveals on pfp load, tint fades in via CSS
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
42fe5d802b
commit
b436e39f40
1 file changed
+23
-20
+23
-20
@@ -113,46 +113,49 @@ export async function loadArtistDetail(artist) {
|
|||||||
])
|
])
|
||||||
: [{ status: 'rejected' }, { status: 'rejected' }];
|
: [{ status: 'rejected' }, { status: 'rejected' }];
|
||||||
|
|
||||||
// ── Hero ── (await color before showing anything so it all renders at once)
|
// ── Hero ── non-blocking: set bg/pfp immediately, fade in on image load, tint after
|
||||||
const img = imgRes.status === 'fulfilled' ? imgRes.value : null;
|
const img = imgRes.status === 'fulfilled' ? imgRes.value : null;
|
||||||
const _firstAlbums = albumRes.status === 'fulfilled' ? (albumRes.value?.artist?.album || []) : [];
|
const _firstAlbums = albumRes.status === 'fulfilled' ? (albumRes.value?.artist?.album || []) : [];
|
||||||
const _bgCover = _firstAlbums[0] ? coverUrl(_firstAlbums[0].coverArt, 512) : null;
|
const _bgCover = _firstAlbums[0] ? coverUrl(_firstAlbums[0].coverArt, 512) : null;
|
||||||
const bgSrc = img || _bgCover;
|
const bgSrc = img || _bgCover;
|
||||||
|
|
||||||
// _extractColor loads img into canvas — warms the browser cache for the display uses below
|
|
||||||
const [rgb] = await Promise.all([
|
|
||||||
img ? _extractColor(img) : Promise.resolve(null),
|
|
||||||
bgSrc && bgSrc !== img ? new Promise(r => { const i = new Image(); i.onload = i.onerror = r; i.src = bgSrc; }) : Promise.resolve(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if(bgSrc) {
|
if(bgSrc) {
|
||||||
hero.style.background = '';
|
hero.style.background = '';
|
||||||
const bgEl = document.getElementById('artist-hero-bg');
|
const bgEl = document.getElementById('artist-hero-bg');
|
||||||
if(bgEl) bgEl.style.backgroundImage = `url('${bgSrc}')`;
|
if(bgEl) bgEl.style.backgroundImage = `url('${bgSrc}')`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _revealHero = () => requestAnimationFrame(() => {
|
||||||
|
hero.style.transition = 'opacity 0.25s ease';
|
||||||
|
hero.style.opacity = '1';
|
||||||
|
});
|
||||||
|
|
||||||
if(img) {
|
if(img) {
|
||||||
const pfpWrap = document.getElementById('artist-hero-pfp-wrap');
|
const pfpWrap = document.getElementById('artist-hero-pfp-wrap');
|
||||||
if(pfpWrap) {
|
if(pfpWrap) {
|
||||||
const pfpImg = document.createElement('img');
|
const pfpImg = document.createElement('img');
|
||||||
pfpImg.className = 'artist-hero-pfp';
|
pfpImg.className = 'artist-hero-pfp';
|
||||||
pfpImg.alt = '';
|
pfpImg.alt = '';
|
||||||
|
pfpImg.onload = _revealHero;
|
||||||
|
pfpImg.onerror = _revealHero;
|
||||||
pfpImg.src = img;
|
pfpImg.src = img;
|
||||||
pfpWrap.prepend(pfpImg);
|
pfpWrap.prepend(pfpImg);
|
||||||
const initial = document.getElementById('artist-hero-pfp-initial');
|
document.getElementById('artist-hero-pfp-initial')?.style.setProperty('display', 'none');
|
||||||
if(initial) initial.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
|
// color tint — async, fades in via CSS so it never pops
|
||||||
|
_extractColor(img).then(rgb => {
|
||||||
|
if(!rgb) return;
|
||||||
|
const [r, g, b] = rgb;
|
||||||
|
hero.querySelector('.artist-hero-tint')?.remove();
|
||||||
|
const tint = document.createElement('div');
|
||||||
|
tint.className = 'artist-hero-tint';
|
||||||
|
tint.style.cssText = `position:absolute;inset:0;background:linear-gradient(to right,rgba(${r},${g},${b},.55) 0%,rgba(${r},${g},${b},.25) 55%,rgba(${r},${g},${b},.6) 100%);pointer-events:none;opacity:0;transition:opacity 0.5s ease`;
|
||||||
|
if(overlay) hero.insertBefore(tint, overlay);
|
||||||
|
requestAnimationFrame(() => { tint.style.opacity = '1'; });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_revealHero();
|
||||||
}
|
}
|
||||||
if(rgb) {
|
|
||||||
const [r, g, b] = rgb;
|
|
||||||
const tint = document.createElement('div');
|
|
||||||
tint.className = 'artist-hero-tint';
|
|
||||||
tint.style.cssText = `position:absolute;inset:0;background:linear-gradient(to right,rgba(${r},${g},${b},.55) 0%,rgba(${r},${g},${b},.25) 55%,rgba(${r},${g},${b},.6) 100%);pointer-events:none`;
|
|
||||||
if(overlay) hero.insertBefore(tint, overlay);
|
|
||||||
}
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
hero.style.transition = 'opacity 0.3s ease';
|
|
||||||
hero.style.opacity = '1';
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Bio ──
|
// ── Bio ──
|
||||||
const info = infoRes.status === 'fulfilled' ? infoRes.value?.artistInfo2 : null;
|
const info = infoRes.status === 'fulfilled' ? infoRes.value?.artistInfo2 : null;
|
||||||
|
|||||||
Reference in new issue
Block a user