Files
Kikomiko/kikomiko/dist/js/scrub.js
T

57 lines
1.6 KiB
JavaScript

/**
* Vanilla scroll-scrubbed video (no GSAP).
* Pins via CSS sticky; maps scroll progress through spacer to video.currentTime.
*/
export function initScrollScrub() {
const root = document.querySelector("[data-scroll-scrub]");
if (!root) return;
const video = root.querySelector("video");
const spacer = root.querySelector(".scrub-spacer");
if (!(video instanceof HTMLVideoElement) || !spacer) return;
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
video.removeAttribute("autoplay");
video.controls = true;
spacer.style.display = "none";
return;
}
let ready = false;
let seeking = false;
let target = 0;
const onReady = () => {
ready = true;
video.pause();
};
if (video.readyState >= 2) onReady();
else video.addEventListener("loadeddata", onReady, { once: true });
video.addEventListener("seeked", () => {
seeking = false;
if (Math.abs(video.currentTime - target) > 0.04) {
seeking = true;
video.currentTime = target;
}
});
function update() {
if (!ready || !video.duration) return;
const rect = spacer.getBoundingClientRect();
const total = spacer.offsetHeight - window.innerHeight;
const scrolled = -rect.top;
const progress = total > 0 ? Math.min(1, Math.max(0, scrolled / total)) : 0;
target = progress * video.duration;
if (!seeking && Math.abs(video.currentTime - target) > 0.04) {
seeking = true;
video.currentTime = target;
}
}
window.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
update();
}