Fix slideshow crossfade flash — wait for image load before fading in

Previously the active class was applied via requestAnimationFrame
before the image had decoded, causing a brief blank-then-flash.
Now loadSlide waits for onload before transitioning, and advanceSlide
checks complete/naturalWidth (or waits for onload) on the preloaded
slot before doing the swap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 21:41:25 +12:00
parent afddfd5bb1
commit 1e97e7c805

View File

@@ -302,10 +302,17 @@ function hideSlideshow() {
function loadSlide(slot, url) {
const img = document.getElementById(`slide-${slot}`);
img.src = url;
if (slot === activeSlot) {
// Slight delay lets the browser decode before fading in
requestAnimationFrame(() => requestAnimationFrame(() => img.classList.add('active')));
// Only fade in once the image is fully decoded — no blank-then-flash
img.onload = () => { img.onload = null; img.classList.add('active'); };
img.src = url;
// Handle cached images that won't fire onload
if (img.complete && img.naturalWidth > 0) {
img.onload = null;
img.classList.add('active');
}
} else {
img.src = url; // preload only
}
}
@@ -314,13 +321,20 @@ function advanceSlide() {
const current = document.getElementById(`slide-${activeSlot}`);
const next = document.getElementById(`slide-${nextSlot}`);
// Fade in the preloaded next image, fade out current
next.classList.add('active');
current.classList.remove('active');
activeSlot = nextSlot;
const doSwap = () => {
next.onload = null;
next.classList.add('active');
current.classList.remove('active');
activeSlot = nextSlot;
// Preload the upcoming photo into the now-hidden slot
slideIndex = (slideIndex + 1) % photos.length;
current.src = photos[(slideIndex + 1) % photos.length];
};
// Preload the one after next into the now-hidden slot
slideIndex = (slideIndex + 1) % photos.length;
const upcoming = photos[(slideIndex + 1) % photos.length];
current.src = upcoming;
// If the preloaded image is ready, swap immediately; otherwise wait for it
if (next.complete && next.naturalWidth > 0) {
doSwap();
} else {
next.onload = doSwap;
}
}