fix(story): nav title cross-fades scroll-driven as hero content exits viewport
Replaced IntersectionObserver (discrete threshold) with a scroll RAF loop using getBoundingClientRect. Opacity is computed from the fraction of .story-hero__content still visible above the viewport top — so the nav title fades in gradually as the hero title slides off the top edge, reaching full opacity only when the element is completely gone. Removed CSS transition (no longer needed; per-frame JS update is smooth). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
@@ -88,20 +88,37 @@
|
||||
update();
|
||||
})();
|
||||
|
||||
/* ── Story title in nav (fades in when hero title leaves viewport) ─────── */
|
||||
/* ── Story title in nav (cross-fades as hero content exits viewport top) ── */
|
||||
(function () {
|
||||
var navTitle = document.getElementById('story-nav-title');
|
||||
var heroContent = document.querySelector('.story-hero__content');
|
||||
if (!navTitle || !heroContent) return;
|
||||
var hasBeenVisible = false;
|
||||
new IntersectionObserver(function (entries) {
|
||||
if (entries[0].isIntersecting) {
|
||||
hasBeenVisible = true;
|
||||
navTitle.classList.remove('is-visible');
|
||||
} else if (hasBeenVisible) {
|
||||
navTitle.classList.add('is-visible');
|
||||
var ticking = false;
|
||||
|
||||
function update() {
|
||||
var rect = heroContent.getBoundingClientRect();
|
||||
var inView = rect.bottom > 0 && rect.top < window.innerHeight;
|
||||
if (inView) hasBeenVisible = true;
|
||||
|
||||
if (hasBeenVisible) {
|
||||
var opacity;
|
||||
if (rect.bottom <= 0) {
|
||||
opacity = 1; // fully above viewport
|
||||
} else if (rect.top <= 0) {
|
||||
opacity = 1 - rect.bottom / rect.height; // partially exiting top
|
||||
} else {
|
||||
opacity = 0; // fully in viewport
|
||||
}
|
||||
navTitle.style.opacity = opacity.toFixed(3);
|
||||
}
|
||||
}, { threshold: 0 }).observe(heroContent);
|
||||
ticking = false;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function () {
|
||||
if (!ticking) { requestAnimationFrame(update); ticking = true; }
|
||||
}, { passive: true });
|
||||
update();
|
||||
})();
|
||||
|
||||
/* ── Back to top button ─────────────────────────────────── */
|
||||
|
||||
Reference in New Issue
Block a user