60 lines
3.1 KiB
JavaScript
60 lines
3.1 KiB
JavaScript
// scroll.js
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// 1) Vertical “zoom‑in/out” on .scroll‑section using IntersectionObserver
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
const sections = document.querySelectorAll('.scroll-section');
|
||
const io = new IntersectionObserver((entries) => {
|
||
entries.forEach(entry => {
|
||
entry.target.classList.toggle('in-view', entry.isIntersecting);
|
||
});
|
||
}, { threshold: 0.15 });
|
||
sections.forEach(sec => io.observe(sec));
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// 2) Horizontal‑scroll “pin & pan” for the Hobbies section
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
const wrapper = document.getElementById('hobbies');
|
||
if (!wrapper) return; // no Hobbies section → exit
|
||
|
||
// The element that will stay stuck in the viewport:
|
||
const stickySection = wrapper.querySelector('.horizontal-section');
|
||
// The inner flex row we translate left/right:
|
||
const inner = stickySection.querySelector('.horizontal-section__inner');
|
||
|
||
// A) Make the section itself “sticky” at the top of the viewport
|
||
stickySection.style.position = 'sticky';
|
||
stickySection.style.top = '3rem';
|
||
stickySection.style.height = '100vh';
|
||
stickySection.style.overflow = 'hidden';
|
||
|
||
// B) Compute how far we need to scroll to reveal all cards
|
||
let containerW = wrapper.clientWidth; // e.g. 70vw in px
|
||
let scrollableDist = inner.scrollWidth - containerW; // total horizontal span minus one screen
|
||
|
||
// C) Stretch the wrapper’s vertical height so that
|
||
// scrolling wrapperHeight(px) → moving inner by scrollableDist(px)
|
||
wrapper.style.height = `${window.innerHeight + scrollableDist}px`;
|
||
|
||
// D) On scroll, when within the wrapper’s “pin zone,”
|
||
// translate the inner row instead of moving vertically
|
||
window.addEventListener('scroll', () => {
|
||
const y = window.scrollY;
|
||
const top = wrapper.offsetTop;
|
||
const end = top + scrollableDist;
|
||
|
||
if (y >= top && y <= end) {
|
||
// map vertical scroll → horizontal translate
|
||
inner.style.transform = `translateX(-${y - top}px)`;
|
||
}
|
||
});
|
||
|
||
// E) Recompute on resize
|
||
window.addEventListener('resize', () => {
|
||
containerW = wrapper.clientWidth;
|
||
scrollableDist = inner.scrollWidth - containerW;
|
||
wrapper.style.height = `${window.innerHeight + scrollableDist}px`;
|
||
});
|
||
});
|