fix: hero reveals on image load only, color tint non-blocking CSS fade
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
28de177381
commit
55cfaf0392
1 file changed
+26
-31
+26
-31
@@ -119,36 +119,25 @@ export async function loadArtistDetail(artist) {
|
|||||||
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;
|
||||||
|
|
||||||
// Gate reveal on pfp + bg + color all ready — nothing shows until everything is set
|
// Reveal when images are ready; color tint fades in after (non-blocking)
|
||||||
let _pfpReady = false, _bgReady = false, _colorReady = false;
|
let _pfpReady = false, _bgReady = false;
|
||||||
let _heroRgb = null;
|
|
||||||
|
|
||||||
const _revealHero = () => {
|
const _revealHero = () => {
|
||||||
if(!_pfpReady || !_bgReady || !_colorReady) return;
|
if(!_pfpReady || !_bgReady) return;
|
||||||
if(_heroRgb) {
|
requestAnimationFrame(() => { hero.style.transition = 'opacity 0.25s ease'; hero.style.opacity = '1'; });
|
||||||
const [r, g, b] = _heroRgb;
|
|
||||||
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`;
|
|
||||||
if(overlay) hero.insertBefore(tint, overlay);
|
|
||||||
}
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
hero.style.transition = 'opacity 0.25s ease';
|
|
||||||
hero.style.opacity = '1';
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Preload bg — only set background-image after it's in cache
|
|
||||||
if(bgSrc) {
|
if(bgSrc) {
|
||||||
hero.style.background = '';
|
hero.style.background = '';
|
||||||
const bgEl = document.getElementById('artist-hero-bg');
|
const bgEl = document.getElementById('artist-hero-bg');
|
||||||
const _bgImg = new Image();
|
if(bgSrc === img) {
|
||||||
_bgImg.onload = _bgImg.onerror = () => {
|
// same URL as pfp — browser cache will have it when pfp loads, no extra request
|
||||||
if(bgEl) bgEl.style.backgroundImage = `url('${bgSrc}')`;
|
bgEl.style.backgroundImage = `url('${bgSrc}')`;
|
||||||
_bgReady = true; _revealHero();
|
_bgReady = true;
|
||||||
};
|
} else {
|
||||||
_bgImg.src = bgSrc;
|
const _bgPreload = new Image();
|
||||||
|
_bgPreload.onload = _bgPreload.onerror = () => { bgEl.style.backgroundImage = `url('${bgSrc}')`; _bgReady = true; _revealHero(); };
|
||||||
|
_bgPreload.src = bgSrc;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_bgReady = true;
|
_bgReady = true;
|
||||||
}
|
}
|
||||||
@@ -163,13 +152,19 @@ export async function loadArtistDetail(artist) {
|
|||||||
pfpImg.src = img;
|
pfpImg.src = img;
|
||||||
pfpWrap.prepend(pfpImg);
|
pfpWrap.prepend(pfpImg);
|
||||||
document.getElementById('artist-hero-pfp-initial')?.style.setProperty('display', 'none');
|
document.getElementById('artist-hero-pfp-initial')?.style.setProperty('display', 'none');
|
||||||
} else {
|
} else { _pfpReady = true; }
|
||||||
_pfpReady = true;
|
// color tint is non-blocking — fades in via CSS whenever it's ready
|
||||||
}
|
_extractColor(img).then(rgb => {
|
||||||
_extractColor(img).then(rgb => { _heroRgb = rgb; _colorReady = true; _revealHero(); });
|
if(!rgb) return;
|
||||||
} else {
|
const [r, g, b] = rgb;
|
||||||
_pfpReady = true; _colorReady = true; _revealHero();
|
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.6s ease`;
|
||||||
|
if(overlay) hero.insertBefore(tint, overlay);
|
||||||
|
requestAnimationFrame(() => { tint.style.opacity = '1'; });
|
||||||
|
});
|
||||||
|
} else { _pfpReady = true; _revealHero(); }
|
||||||
|
|
||||||
// ── 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