67 lines
2.6 KiB
JavaScript
67 lines
2.6 KiB
JavaScript
// modules/scroll-loop/index.js
|
|
import { registerFrameTask } from '../../core/frameloop.js';
|
|
|
|
export function init(config = {}) {
|
|
const elements = document.querySelectorAll('[data-scroll-loop]');
|
|
|
|
elements.forEach(el => {
|
|
const type = el.dataset.scrollType || 'translate';
|
|
if (type === 'translate' && el.children.length === 1) {
|
|
const clone = el.firstElementChild.cloneNode(true);
|
|
clone.setAttribute('aria-hidden', 'true');
|
|
el.appendChild(clone);
|
|
}
|
|
});
|
|
|
|
registerFrameTask('scroll-loop', () => {
|
|
const scrollY = window.scrollY;
|
|
const scrollX = window.scrollX;
|
|
|
|
elements.forEach(el => {
|
|
const factor = parseFloat(el.dataset.scrollSpeed || config.speed || 0.2);
|
|
const axis = el.dataset.scrollAxis || 'y';
|
|
const type = el.dataset.scrollType || 'translate';
|
|
const pause = el.dataset.loopPause === 'true';
|
|
const offsetStart = parseFloat(el.dataset.loopOffset || 0);
|
|
const limit = parseFloat(el.dataset.loopLimit || 0);
|
|
|
|
const input = axis === 'x' ? scrollX : scrollY;
|
|
if (limit && input > limit) return;
|
|
if (pause && (el.matches(':hover') || el.matches(':active'))) return;
|
|
|
|
const offset = (input + offsetStart) * factor;
|
|
|
|
switch (type) {
|
|
case 'translate': {
|
|
const base = axis === 'x' ? el.offsetWidth : el.offsetHeight;
|
|
const value = -(offset % base);
|
|
const transform = axis === 'x' ? `translateX(${value}px)` : `translateY(${value}px)`;
|
|
el.style.transform = transform;
|
|
break;
|
|
}
|
|
case 'rotate': {
|
|
const deg = offset % 360;
|
|
el.style.transform = `rotate(${deg}deg)`;
|
|
break;
|
|
}
|
|
case 'background': {
|
|
const pos = offset % 100;
|
|
if (axis === 'x') {
|
|
el.style.backgroundPosition = `${pos}% center`;
|
|
} else {
|
|
el.style.backgroundPosition = `center ${pos}%`;
|
|
}
|
|
break;
|
|
}
|
|
case 'scale': {
|
|
const scale = 1 + Math.sin(offset * 0.01) * 0.1;
|
|
el.style.transform = `scale(${scale.toFixed(3)})`;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
}, { autoStart: true });
|
|
}
|