Files
portfolio/script/scroll.js
2025-08-11 22:18:02 +08:00

60 lines
3.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// scroll.js
document.addEventListener('DOMContentLoaded', () => {
// ─────────────────────────────────────────────────────────────────────────────
// 1) Vertical “zoomin/out” on .scrollsection 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) Horizontalscroll “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 wrappers 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 wrappers “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`;
});
});