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
JavaScript
/*!
* 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 };