Advanced GSAP Animations
This recipe demonstrates how to create sophisticated animations using GSAP (GreenSock Animation Platform) with TresJS for smooth, performance-optimized animations with advanced features like staggering and timeline control.
Install GSAP
First, install GSAP as a dependency in your project:
npm install gsap
Import required modules
Import GSAP and the necessary Vue composables. Use shallowRef
for better performance with Three.js objects:
import { shallowRef, watch } from 'vue'
import { OrbitControls } from '@tresjs/cientos'
import gsap from 'gsap'
shallowRef
instead of ref
to avoid unnecessary reactivity on Three.js objects, which improves performance.Create multiple objects to animate
Set up an array of positions for multiple boxes that will be animated with stagger effects:
const boxesRef = shallowRef()
const zs = []
for (let z = -4.5; z <= 4.5; z++) {
zs.push(z)
}
Set up the scene structure
Create a group of meshes that will be animated together:
<template>
<TresPerspectiveCamera :position="[-15, 10, 15]" />
<OrbitControls />
<TresGroup ref="boxesRef">
<TresMesh v-for="(z, i) of zs" :key="i" :position="[0, 0.5, z]">
<TresBoxGeometry />
<TresMeshNormalMaterial />
</TresMesh>
</TresGroup>
<TresGridHelper :args="[10, 10, 0x444444, 'teal']" />
</template>
Create the GSAP staggered animation
Use Vue's watch
to set up the animation when the template ref is available:
watch(boxesRef, () => {
if (!boxesRef.value) return
// Get positions and rotations for all boxes
const positions = Array.from(boxesRef.value.children).map(
(child) => child.position
)
const rotations = Array.from(boxesRef.value.children).map(
(child) => child.rotation
)
const animProperties = {
ease: 'power1.inOut',
duration: 1,
stagger: {
each: 0.25,
repeat: -1,
yoyo: true,
},
}
// Animate positions
gsap.to(positions, {
y: 2.5,
...animProperties,
})
// Animate rotations
gsap.to(rotations, {
x: 2,
...animProperties,
})
})
Understanding GSAP Stagger Options
The stagger
property provides powerful control over timing:
const animProperties = {
ease: 'power1.inOut', // Easing function
duration: 1, // Animation duration in seconds
stagger: {
each: 0.25, // Delay between each object (0.25s)
repeat: -1, // Infinite repeat (-1)
yoyo: true, // Reverse on alternate cycles
from: 'start', // Animation direction (start, center, end)
},
}
Advanced Techniques
Timeline Control
For more complex sequences, use GSAP timelines to coordinate multiple animations:
<script setup lang="ts">
import { shallowRef, watch, onMounted } from 'vue'
import gsap from 'gsap'
const groupRef = shallowRef()
const timeline = gsap.timeline({ paused: true })
watch(groupRef, () => {
if (!groupRef.value) return
const children = Array.from(groupRef.value.children)
// Clear existing timeline
timeline.clear()
// Add multiple animations to timeline
timeline
.to(children.map(child => child.position), {
y: 3,
duration: 1,
ease: 'back.out(1.7)',
stagger: 0.1
})
.to(children.map(child => child.rotation), {
y: Math.PI * 2,
duration: 2,
ease: 'power2.inOut',
stagger: 0.1
}, '-=0.5') // Start 0.5s before previous animation ends
.to(children.map(child => child.scale), {
x: 1.5,
y: 1.5,
z: 1.5,
duration: 0.5,
ease: 'elastic.out(1, 0.3)',
stagger: 0.05
})
})
// Control functions
const playAnimation = () => timeline.play()
const pauseAnimation = () => timeline.pause()
const reverseAnimation = () => timeline.reverse()
const restartAnimation = () => timeline.restart()
</script>
Performance Optimization
When animating many objects, optimize performance by:
- Use
shallowRef
for Three.js object references - Batch property access to avoid repeated DOM queries
- Use GSAP's
set()
method for immediate property changes - Leverage hardware acceleration with
force3D: true
// Optimized animation setup
const optimizedAnimation = () => {
// Get all properties at once
const meshes = Array.from(boxesRef.value.children)
const positions = meshes.map(mesh => mesh.position)
const rotations = meshes.map(mesh => mesh.rotation)
// Use force3D for hardware acceleration
gsap.to(positions, {
y: 2,
duration: 1,
force3D: true,
ease: 'power2.out'
})
}
Animation Events
GSAP provides powerful callback events to sync with your application state:
gsap.to(positions, {
y: 2,
duration: 1,
stagger: 0.1,
onStart: () => console.log('Animation started'),
onComplete: () => console.log('Animation completed'),
onUpdate: function() {
// Called on every frame
console.log('Progress:', this.progress())
},
onRepeat: () => console.log('Animation repeated')
})