UNPKG

gsap-dattebayo

Version:

The ultimate GSAP-powered scroll animation library - Simple as AOS, powerful as GSAP. Modern animations for 2025-2026 web trends.

441 lines (434 loc) 13.4 kB
/*! * GSAP Dattebayo v0.1.0-alpha.1 * The ultimate GSAP-powered scroll animation library * https://github.com/serdjan/gsap-dattebayo * * Copyright 2025 GSAP Dattebayo * Released under the MIT License */ import gsap from 'gsap'; import 'gsap/ScrollTrigger'; import SplitText from 'gsap/SplitText'; /** * Helper utilities for GSAP Dattebayo */ /** * Convert selector or element to array of HTMLElements */ function toArray(target) { if (typeof target === 'string') { return Array.from(document.querySelectorAll(target)); } if (target instanceof HTMLElement) { return [target]; } if (target instanceof NodeList) { return Array.from(target); } if (Array.isArray(target)) { return target; } return []; } /** * Character-by-character reveal animations * Uses GSAP SplitText (free since 2025) */ /** * Character stagger reveal - Classic typewriter-style */ function charReveal(target, options = {}) { const { duration = 1, ease = 'power2.out', delay = 0, stagger = 0.05, from = 'start' } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); tl.from(split.chars, { opacity: 0, y: 20, rotationX: -90, transformOrigin: '0% 50% -50', duration, ease, stagger: { each: stagger, from }, force3D: true }, 0); }); return tl; } /** * Character fade up - Simple fade with upward movement */ function charFadeUp(target, options = {}) { const { duration = 0.6, ease = 'power2.out', delay = 0, stagger = 0.03, distance = 30 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); tl.from(split.chars, { opacity: 0, y: distance, duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Character wave - Wave-like stagger effect */ function charWave(target, options = {}) { const { duration = 0.6, ease = 'back.out(1.7)', delay = 0, stagger = 0.05 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); tl.from(split.chars, { opacity: 0, y: -50, rotation: 10, scale: 0, duration, ease, stagger: { each: stagger, from: 'center' }, force3D: true }, 0); }); return tl; } /** * Character elastic - Bouncy scale reveal (2025 trend) */ function charElastic(target, options = {}) { const { duration = 1, ease = 'elastic.out(1, 0.3)', delay = 0, stagger = 0.04 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); tl.from(split.chars, { opacity: 0, scale: 0, rotation: 360, transformOrigin: 'center center', duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Character blur in - Blur to focus per character (modern) */ function charBlur(target, options = {}) { const { duration = 0.8, ease = 'power2.out', delay = 0, stagger = 0.03 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); tl.from(split.chars, { opacity: 0, filter: 'blur(10px)', scale: 1.5, duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Word-by-word reveal animations * Uses GSAP SplitText for word-level animations */ /** * Word fade up - Words reveal with upward movement */ function wordReveal(target, options = {}) { const { duration = 0.8, ease = 'power2.out', delay = 0, stagger = 0.1, distance = 30, from = 'start' } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'words' }); tl.from(split.words, { opacity: 0, y: distance, duration, ease, stagger: { each: stagger, from }, force3D: true }, 0); }); return tl; } /** * Word scale in - Words pop in with scale */ function wordScaleIn(target, options = {}) { const { duration = 0.6, ease = 'back.out(1.7)', delay = 0, stagger = 0.08 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'words' }); tl.from(split.words, { opacity: 0, scale: 0, transformOrigin: 'center center', duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Word rotate in - 3D rotation reveal per word */ function wordRotateIn(target, options = {}) { const { duration = 0.8, ease = 'power2.out', delay = 0, stagger = 0.1 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'words' }); tl.from(split.words, { opacity: 0, rotationY: -90, transformOrigin: 'left center', transformPerspective: 800, duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Word slide alternate - Words slide from alternating directions */ function wordSlideAlternate(target, options = {}) { const { duration = 0.8, ease = 'power3.out', delay = 0, stagger = 0.08, distance = 50 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'words' }); split.words.forEach((word, i) => { tl.from(word, { opacity: 0, x: i % 2 === 0 ? -distance : distance, duration, ease, force3D: true }, i * stagger); }); }); return tl; } /** * Line-by-line reveal animations * Uses GSAP SplitText for line-level animations */ /** * Line reveal - Classic line-by-line fade up */ function lineReveal(target, options = {}) { const { duration = 1, ease = 'power3.out', delay = 0, stagger = 0.15, distance = 50 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'lines', linesClass: 'line' }); tl.from(split.lines, { opacity: 0, y: distance, duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Line clip reveal - Mask-based reveal (modern effect) */ function lineClipReveal(target, options = {}) { const { duration = 1.2, ease = 'power4.out', delay = 0, stagger = 0.1 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'lines', linesClass: 'line' }); // Wrap lines for overflow hidden split.lines.forEach(line => { const wrapper = document.createElement('div'); wrapper.style.overflow = 'hidden'; line.parentNode?.insertBefore(wrapper, line); wrapper.appendChild(line); }); tl.from(split.lines, { yPercent: 100, duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Line slide alternate - Lines slide from alternating sides */ function lineSlideAlternate(target, options = {}) { const { duration = 1, ease = 'power2.out', delay = 0, stagger = 0.12, distance = 100 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'lines' }); split.lines.forEach((line, i) => { tl.from(line, { opacity: 0, x: i % 2 === 0 ? -distance : distance, duration, ease, force3D: true }, i * stagger); }); }); return tl; } /** * Line scale reveal - Lines scale in from center */ function lineScaleReveal(target, options = {}) { const { duration = 1, ease = 'back.out(1.7)', delay = 0, stagger = 0.1 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'lines' }); tl.from(split.lines, { opacity: 0, scaleX: 0, transformOrigin: 'left center', duration, ease, stagger, force3D: true }, 0); }); return tl; } /** * Scramble/Glitch text animations * Modern cyberpunk-style text reveals */ /** * Scramble text reveal - GSAP ScrambleText plugin */ function scrambleReveal(target, options = {}) { const { duration = 2, delay = 0, chars = 'lowerCase' } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const originalText = element.textContent || ''; tl.to(element, { scrambleText: { text: originalText, chars: chars, speed: 0.3 }, duration: duration, ease: 'none' }, 0); }); return tl; } /** * Glitch reveal - Digital glitch effect */ function glitchReveal(target, options = {}) { const { duration = 1.5, ease = 'power2.out', delay = 0 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { // Clone original text for glitch layers element.textContent || ''; element.style.position = 'relative'; // Create glitch effect with multiple rapid animations const glitchCount = 8; for (let i = 0; i < glitchCount; i++) { const glitchDelay = (duration / glitchCount) * i; tl.fromTo(element, { opacity: 0, x: Math.random() * 10 - 5, skewX: Math.random() * 20 - 10, filter: `hue-rotate(${Math.random() * 360}deg)` }, { opacity: 1, x: 0, skewX: 0, filter: 'hue-rotate(0deg)', duration: duration / glitchCount, ease, force3D: true }, glitchDelay); } }); return tl; } /** * Matrix reveal - Matrix-style falling characters */ function matrixReveal(target, options = {}) { const { duration = 2, delay = 0, chars = '01', stagger = 0.05 } = options; const elements = toArray(target); const tl = gsap.timeline({ delay }); elements.forEach(element => { const split = new SplitText(element, { type: 'chars' }); const getRandomChar = () => chars.charAt(Math.floor(Math.random() * chars.length)); split.chars.forEach((char, i) => { const originalChar = char.textContent || ''; // Scramble phase const scrambleDuration = duration * 0.7; const revealAt = scrambleDuration + i * stagger; // Rapid character changes for (let j = 0; j < 10; j++) { tl.to({}, { duration: scrambleDuration / 10, onStart: () => { char.textContent = getRandomChar(); } }, (scrambleDuration / 10) * j); } // Final reveal tl.to({}, { duration: 0.1, onComplete: () => { char.textContent = originalChar; } }, revealAt); // Fade in tl.from(char, { opacity: 0, y: -20, duration: 0.3, ease: 'power2.out', force3D: true }, revealAt); }); }); return tl; } export { charBlur, charElastic, charFadeUp, charReveal, charWave, glitchReveal, lineClipReveal, lineReveal, lineScaleReveal, lineSlideAlternate, matrixReveal, scrambleReveal, wordReveal, wordRotateIn, wordScaleIn, wordSlideAlternate };