Appearance
GSAP Animations
This guide explains GSAP animation patterns and best practices in LamaPress.
Table of Contents
- Overview
- GSAP Setup
- Animation Patterns
- Timeline Management
- ScrollTrigger
- Best Practices
- Related Documentation
Overview
LamaPress uses GSAP (GreenSock Animation Platform) for all animations. GSAP provides smooth, performant animations with excellent browser support and powerful features like ScrollTrigger.
GSAP Setup
Importing GSAP
Import GSAP in component files:
javascript
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/all'Note: GSAP is configured globally in src/js/core/utils/gsapConfig.js.
Plugin Registration
GSAP plugins are registered automatically:
javascript
// ScrollTrigger is registered globally
gsap.registerPlugin(ScrollTrigger)Animation Patterns
Reveal Animations
Reveal animations in enter() method:
javascript
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/all'
export default class AnimatedSection {
constructor(element) {
this.element = element
this.init()
}
init = () => {
this.title = this.element.querySelector('.js-title')
this.content = this.element.querySelector('.js-content')
// Set initial state
gsap.set([this.title, this.content], {
opacity: 0,
y: 20,
})
}
enter = () => {
this.timeline = gsap.timeline({
scrollTrigger: {
trigger: this.element,
start: 'top 80%',
},
})
this.timeline.to(this.title, {
opacity: 1,
y: 0,
duration: 0.6,
})
this.timeline.to(this.content, {
opacity: 1,
y: 0,
duration: 0.6,
}, '-=0.3') // Start 0.3s before previous animation ends
}
destroy = () => {
this.timeline?.kill()
ScrollTrigger.getAll().forEach(trigger => {
if (trigger.vars.trigger === this.element) {
trigger.kill()
}
})
}
}Hover Animations
Hover animations with mouseenter/mouseleave:
javascript
import gsap from 'gsap'
import { killTimeline } from '@src/js/core/utils/helpers'
export default class HoverCard {
constructor(element) {
this.element = element
this.init()
}
init = () => {
this.image = this.element.querySelector('.js-image')
this.bindEvents()
}
bindEvents = () => {
this.element.addEventListener('mouseenter', this.onMouseEnter)
this.element.addEventListener('mouseleave', this.onMouseLeave)
}
onMouseEnter = () => {
killTimeline(this.hoverTimeline)
this.hoverTimeline = gsap.timeline()
this.hoverTimeline.to(this.image, {
scale: 1.1,
duration: 0.3,
ease: 'power2.out',
})
}
onMouseLeave = () => {
killTimeline(this.hoverTimeline)
this.hoverTimeline = gsap.timeline()
this.hoverTimeline.to(this.image, {
scale: 1,
duration: 0.3,
ease: 'power2.out',
})
}
destroy = () => {
killTimeline(this.hoverTimeline)
this.element.removeEventListener('mouseenter', this.onMouseEnter)
this.element.removeEventListener('mouseleave', this.onMouseLeave)
}
}Scroll Animations
Scroll-based animations with ScrollTrigger:
javascript
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/all'
export default class ScrollAnimation {
constructor(element) {
this.element = element
this.init()
}
init = () => {
this.content = this.element.querySelector('.js-content')
}
enter = () => {
gsap.fromTo(
this.content,
{
opacity: 0,
y: 50,
},
{
opacity: 1,
y: 0,
duration: 1,
ease: 'power3.out',
scrollTrigger: {
trigger: this.element,
start: 'top 80%',
end: 'top 20%',
scrub: true, // Smooth scroll-linked animation
},
}
)
}
destroy = () => {
ScrollTrigger.getAll().forEach(trigger => {
if (trigger.vars.trigger === this.element) {
trigger.kill()
}
})
}
}Timeline Management
Creating Timelines
Create timelines in init() or enter():
javascript
this.timeline = gsap.timeline({
paused: true, // Start paused
onComplete: () => {
// Callback when complete
},
})Killing Timelines
Always kill timelines in destroy():
javascript
destroy = () => {
this.timeline?.kill()
}Or use helper:
javascript
import { killTimeline } from '@src/js/core/utils/helpers'
destroy = () => {
killTimeline(this.timeline)
}ScrollTrigger
Basic ScrollTrigger
Simple scroll-triggered animation:
javascript
gsap.to(element, {
opacity: 1,
scrollTrigger: {
trigger: element,
start: 'top 80%',
},
})Advanced ScrollTrigger
Advanced scroll animations:
javascript
gsap.to(element, {
y: -100,
scrollTrigger: {
trigger: element,
start: 'top top',
end: 'bottom top',
scrub: 1, // Smooth scroll-linked
pin: true, // Pin element during scroll
},
})Best Practices
1. Bind Timelines to Instance
Always bind timelines to component instance:
javascript
this.timeline = gsap.timeline()
// Not: const timeline = gsap.timeline()2. Clean Up in destroy()
Always clean up animations:
javascript
destroy = () => {
this.timeline?.kill()
ScrollTrigger.getAll().forEach(trigger => {
if (trigger.vars.trigger === this.element) {
trigger.kill()
}
})
}3. Use killTimeline() Helper
Use helper function for hover animations:
javascript
import { killTimeline } from '@src/js/core/utils/helpers'
onMouseEnter = () => {
killTimeline(this.hoverTimeline)
// Create new timeline
}Related Documentation
- Component JavaScript - Component structure
- JavaScript Architecture - JavaScript system
- Component Guidelines - Component patterns
Next Steps:
- Review Component JavaScript for component structure
- Check JavaScript Architecture for system overview
- See existing components for animation examples