animex
Version:
Modern animation-on-scroll library with optional GSAP support
123 lines (109 loc) • 2.93 kB
JavaScript
// ==== FILE: animex.js ====
class AnimeX {
constructor(config = {}) {
this.defaults = {
offset: 120,
duration: 800,
easing: "ease",
once: false,
delay: 0,
debug: false,
useGSAP: false,
};
this.settings = { ...this.defaults, ...config };
this.observer = null;
this.init();
}
init() {
this.setupObserver();
this.observeElements();
}
setupObserver() {
this.observer = new IntersectionObserver(
(entries) => entries.forEach((entry) => this.handleIntersection(entry)),
{
rootMargin: `0px 0px -${this.settings.offset}px 0px`,
threshold: 0.1,
}
);
}
handleIntersection(entry) {
const el = entry.target;
const elDelay = parseInt(el.getAttribute("animex-delay") || 0);
const delay = elDelay + (el._animexIndex || 0);
if (entry.isIntersecting) {
setTimeout(() => {
if (
this.settings.useGSAP &&
typeof window !== "undefined" &&
window.gsap
) {
gsap.to(el, {
opacity: 1,
y: 0,
x: 0,
scale: 1,
rotateX: 0,
duration:
parseFloat(
el.getAttribute("animex-duration") || this.settings.duration
) / 1000,
ease: el.getAttribute("animex-easing") || this.settings.easing,
delay: delay / 1000,
});
} else {
el.classList.add("animex-animate");
}
if (this.settings.once) this.observer.unobserve(el);
}, delay);
} else if (!this.settings.once) {
el.classList.remove("animex-animate");
}
}
observeElements() {
let index = 0;
document.querySelectorAll("[animex]").forEach((el) => {
el.style.setProperty(
"--animex-duration",
`${el.getAttribute("animex-duration") || this.settings.duration}ms`
);
el.style.setProperty(
"--animex-easing",
el.getAttribute("animex-easing") || this.settings.easing
);
el._animexIndex = this.settings.delay * index++;
if (this.settings.debug) {
el.style.outline = "1px dashed #3a8dde";
el.style.outlineOffset = "-2px";
}
this.observer.observe(el);
});
}
refresh() {
this.observer.disconnect();
this.init();
}
}
let animexInstance;
function init(config = {}) {
animexInstance = new AnimeX(config);
return animexInstance;
}
function refresh() {
if (animexInstance) animexInstance.refresh();
}
if (typeof window !== "undefined") {
window.AnimeX = { init, refresh };
document.addEventListener("DOMContentLoaded", () => {
init();
});
}
if (typeof window !== "undefined") {
window.AnimeX = { init, refresh };
document.addEventListener("DOMContentLoaded", () => {
init();
});
}
// Pure ESM exports
export { init, refresh };
export default { init, refresh };