54 lines
1.6 KiB
JavaScript
54 lines
1.6 KiB
JavaScript
// modules/scroll-timeline/index.js
|
|
import { Logger } from '../../core/logger.js';
|
|
import { scrollSteps } from './steps.js';
|
|
import {registerFrameTask, unregisterFrameTask} from '../../core/frameloop.js';
|
|
|
|
export function init(userConfig = {}) {
|
|
Logger.info('ScrollTimeline init');
|
|
|
|
const defaultConfig = {
|
|
attribute: 'data-scroll-step',
|
|
triggerPoint: 0.4,
|
|
once: true
|
|
};
|
|
|
|
const config = { ...defaultConfig, ...userConfig };
|
|
|
|
const steps = Array.from(document.querySelectorAll(`[${config.attribute}]`)).map(el => ({
|
|
el,
|
|
index: parseInt(el.getAttribute(config.attribute), 10),
|
|
active: false
|
|
}));
|
|
|
|
function update() {
|
|
const triggerY = window.innerHeight * config.triggerPoint;
|
|
|
|
steps.forEach(step => {
|
|
const rect = step.el.getBoundingClientRect();
|
|
const isVisible = rect.top < triggerY && rect.bottom > 0;
|
|
|
|
if (isVisible && !step.active) {
|
|
step.active = true;
|
|
step.el.classList.add('active');
|
|
Logger.log(`➡️ ENTER step ${step.index}`);
|
|
scrollSteps.onEnter?.(step.index, step.el);
|
|
}
|
|
|
|
if (!isVisible && step.active) {
|
|
step.active = false;
|
|
step.el.classList.remove('active');
|
|
Logger.log(`⬅️ LEAVE step ${step.index}`);
|
|
if (!config.once) {
|
|
scrollSteps.onLeave?.(step.index, step.el);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
registerFrameTask('scroll-timeline', update, { autoStart: true });
|
|
}
|
|
|
|
export function destroy () {
|
|
unregisterFrameTask('scroll-timeline');
|
|
}
|