Vue.js GSAP Integration
Introduction
Animations can significantly enhance the user experience of your web applications, making interactions more intuitive and engaging. While Vue.js provides its native transition system, integrating a specialized animation library like GSAP (GreenSock Animation Platform) unlocks a whole new level of animation capabilities.
GSAP is a robust JavaScript animation library that allows developers to create high-performance, complex animations with minimal code. It's particularly powerful for sequential animations, timeline-based effects, and complex motion paths that might be difficult to achieve with CSS transitions alone.
In this tutorial, we'll explore how to integrate GSAP with Vue.js to create stunning animations that will bring your applications to life.
Prerequisites
Before we begin, you should have:
- Basic knowledge of Vue.js
- Familiarity with JavaScript and ES6 syntax
- A Vue project setup (Vue CLI or Vite)
Installing GSAP
Let's start by installing GSAP in our Vue.js project:
npm install gsap
Or if you're using Yarn:
yarn add gsap
Basic GSAP Integration
Importing GSAP in Vue Components
Once installed, you can import GSAP in any Vue component where you need animations:
<script>
import { gsap } from 'gsap'
export default {
name: 'AnimatedComponent',
// Component options...
}
</script>
Creating a Simple Animation
Let's start with a simple animation that moves a box from left to right when the page loads:
<template>
<div class="animation-container">
<div ref="box" class="box"></div>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
name: 'SimpleAnimation',
mounted() {
gsap.to(this.$refs.box, {
x: 200, // Move 200px to the right
duration: 1, // 1 second
ease: 'power2.out' // Easing function
})
}
}
</script>
<style scoped>
.animation-container {
height: 100px;
position: relative;
}
.box {
width: 50px;
height: 50px;
background-color: #41b883; /* Vue green */
position: absolute;
}
</style>
In this example:
- We create a
box
element and get a reference to it using Vue'sref
attribute - In the
mounted
lifecycle hook, we use GSAP'sto
method to animate the box - The animation moves the box 200px horizontally over 1 second with a smooth easing
GSAP Animation Controls
Triggering Animations on Events
Let's modify our example to trigger the animation when a button is clicked:
<template>
<div class="animation-container">
<div ref="box" class="box"></div>
<button @click="animateBox">Animate Box</button>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
name: 'ControlledAnimation',
methods: {
animateBox() {
gsap.to(this.$refs.box, {
x: this.$refs.box._gsap?.x === 200 ? 0 : 200, // Toggle position
duration: 1,
ease: 'bounce.out'
})
}
}
}
</script>
<style scoped>
.animation-container {
height: 100px;
position: relative;
margin-bottom: 20px;
}
.box {
width: 50px;
height: 50px;
background-color: #41b883;
position: absolute;
}
button {
position: absolute;
top: 60px;
}
</style>
Now the animation only runs when the button is clicked, and it toggles the box position between its original location and 200px to the right.
Creating Animation Timelines
GSAP's Timeline feature is particularly powerful for creating sequences of animations. Here's how to create a simple timeline:
<template>
<div class="animation-container">
<div ref="box1" class="box box1"></div>
<div ref="box2" class="box box2"></div>
<div ref="box3" class="box box3"></div>
<button @click="playTimeline">Play Timeline</button>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
name: 'TimelineAnimation',
data() {
return {
timeline: null
}
},
mounted() {
// Create a timeline but don't play it yet
this.timeline = gsap.timeline({ paused: true })
.to(this.$refs.box1, { x: 200, duration: 1 })
.to(this.$refs.box2, { x: 200, duration: 1 }, "-=0.5") // Start 0.5s before previous animation ends
.to(this.$refs.box3, { x: 200, duration: 1 }, "-=0.5")
},
methods: {
playTimeline() {
// Play the timeline when the button is clicked
this.timeline.restart()
}
}
}
</script>
<style scoped>
.animation-container {
height: 200px;
position: relative;
}
.box {
width: 50px;
height: 50px;
position: absolute;
}
.box1 {
background-color: #41b883;
top: 0;
}
.box2 {
background-color: #35495e;
top: 60px;
}
.box3 {
background-color: #ff7e67;
top: 120px;
}
button {
position: absolute;
top: 180px;
}
</style>
This example creates a staggered sequence where each box starts moving before the previous one has finished.
Advanced GSAP Features in Vue
Using GSAP Plugins
GSAP offers various plugins for enhanced animations. Let's use the ScrollTrigger
plugin to create a scroll-based animation:
First, import and register the plugin:
<script>
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
// Register the plugin
gsap.registerPlugin(ScrollTrigger)
</script>
Then create a scroll-triggered animation:
<template>
<div>
<div class="spacer"></div>
<div class="scroll-container">
<div ref="scrollBox" class="scroll-box">
Scroll down to animate me!
</div>
</div>
<div class="spacer"></div>
</div>
</template>
<script>
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
export default {
name: 'ScrollAnimation',
mounted() {
gsap.from(this.$refs.scrollBox, {
x: -200,
opacity: 0,
duration: 1,
scrollTrigger: {
trigger: this.$refs.scrollBox,
start: "top bottom", // when the top of the element hits the bottom of the viewport
end: "top center", // when the top of the element hits the center of the viewport
scrub: true, // smooth scrubbing
toggleActions: "play none none reverse"
}
})
}
}
</script>
<style scoped>
.spacer {
height: 100vh;
}
.scroll-container {
height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
.scroll-box {
width: 300px;
height: 100px;
background-color: #41b883;
color: white;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
</style>
This animation will trigger as the user scrolls down to the element, and reverse when scrolling back up.
Integrating with Vue's Reactive System
We can leverage Vue's reactivity system to dynamically control GSAP animations:
<template>
<div class="reactive-container">
<div ref="reactiveBox" class="reactive-box">
{{ message }}
</div>
<div class="controls">
<button @click="changeColor('blue')">Blue</button>
<button @click="changeColor('green')">Green</button>
<button @click="changeColor('red')">Red</button>
<input v-model.number="boxSize" type="range" min="50" max="200" />
<span>Size: {{ boxSize }}px</span>
</div>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
name: 'ReactiveAnimation',
data() {
return {
boxColor: 'blue',
boxSize: 100,
message: 'Reactive Animation!'
}
},
watch: {
boxColor(newColor) {
gsap.to(this.$refs.reactiveBox, {
backgroundColor: newColor,
duration: 0.5
})
},
boxSize(newSize) {
gsap.to(this.$refs.reactiveBox, {
width: newSize,
height: newSize,
duration: 0.3
})
}
},
methods: {
changeColor(color) {
this.boxColor = color
}
}
}
</script>
<style scoped>
.reactive-container {
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.reactive-box {
width: 100px;
height: 100px;
background-color: blue;
color: white;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
button {
padding: 5px 15px;
}
</style>
In this example, we use Vue's watch property to monitor changes to our reactive data and trigger GSAP animations accordingly.
Practical Example: Creating a Modal Animation
Let's create a practical example of a modal with entrance and exit animations:
<template>
<div>
<button @click="toggleModal">Show Modal</button>
<div v-if="isModalVisible" class="modal-overlay" @click="toggleModal">
<div ref="modalContent" class="modal-content" @click.stop>
<h2>Animated Modal</h2>
<p>This modal is animated with GSAP!</p>
<button @click="toggleModal">Close</button>
</div>
</div>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
name: 'AnimatedModal',
data() {
return {
isModalVisible: false
}
},
methods: {
toggleModal() {
if (this.isModalVisible) {
// If modal is visible, animate it out before hiding
this.animateModalOut().then(() => {
this.isModalVisible = false
})
} else {
// Show modal and animate it in
this.isModalVisible = true
this.$nextTick(() => {
this.animateModalIn()
})
}
},
animateModalIn() {
gsap.fromTo(
this.$refs.modalContent,
{ scale: 0.8, opacity: 0, y: -20 },
{ scale: 1, opacity: 1, y: 0, duration: 0.5, ease: 'back.out(1.7)' }
)
},
animateModalOut() {
return gsap.to(this.$refs.modalContent, {
scale: 0.8,
opacity: 0,
y: -20,
duration: 0.3,
ease: 'power2.in'
})
}
}
}
</script>
<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 8px;
width: 400px;
max-width: 90%;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
button {
padding: 8px 16px;
background-color: #41b883;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
This modal animation demonstrates how GSAP can be used to create polished UI interactions. When the modal appears, it scales up and fades in with a slight bounce effect. When closing, it scales down, fades out, and moves up slightly.
Composition API and GSAP
If you're using Vue 3 with the Composition API, here's how you can integrate GSAP:
<template>
<div class="composition-container">
<div ref="animatedElement" class="animated-element"></div>
<button @click="triggerAnimation">Animate</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { gsap } from 'gsap'
const animatedElement = ref(null)
const tl = ref(null)
onMounted(() => {
// Create a timeline for later use
tl.value = gsap.timeline({ paused: true })
.to(animatedElement.value, {
rotation: 360,
x: 100,
duration: 1
})
.to(animatedElement.value, {
backgroundColor: '#ff7e67',
borderRadius: '50%',
duration: 0.5
})
.to(animatedElement.value, {
x: 0,
scale: 1.2,
duration: 0.8,
ease: 'elastic.out(1, 0.3)'
})
})
const triggerAnimation = () => {
tl.value.restart()
}
</script>
<style scoped>
.composition-container {
height: 200px;
position: relative;
}
.animated-element {
width: 80px;
height: 80px;
background-color: #41b883;
margin-bottom: 20px;
}
button {
padding: 8px 16px;
}
</style>
Performance Considerations
When integrating GSAP with Vue, keep these performance tips in mind:
-
Use object pooling: For repetitive animations, reuse the same objects rather than creating new ones.
-
Be mindful of watchers: When animating based on reactive data changes, use debouncing or throttling for frequently changing values.
-
Use the will-change property: For complex animations, add the CSS will-change property to elements that will be animated.
.animated-element {
will-change: transform, opacity;
}
- Leverage GSAP's built-in optimizations: GSAP automatically uses requestAnimationFrame and optimizes animations under the hood.
Debugging GSAP Animations
GSAP provides several tools for debugging animations:
// Add this to see the current state of a GSAP animation
gsap.to(element, {
x: 100,
duration: 1,
onUpdate: function() {
console.log(this.progress(), this.targets()[0]._gsap);
}
})
You can also use GSAP's GSDevTools
plugin for more advanced debugging, though it requires the premium Club GreenSock membership.
Summary
Integrating GSAP with Vue.js gives you powerful animation capabilities that can significantly enhance your application's user experience. We've covered:
- Basic GSAP setup and integration with Vue components
- Creating simple animations and controlling them with events
- Building sequential animations with GSAP timelines
- Using GSAP plugins like ScrollTrigger
- Integrating with Vue's reactivity system
- Creating practical UI animations like modals
- Using GSAP with Vue's Composition API
The combination of Vue's reactivity and component system with GSAP's animation power provides an excellent foundation for building engaging, dynamic interfaces.
Additional Resources
To continue your learning journey with GSAP and Vue:
Exercises
-
Create a card flip animation using GSAP and Vue that reveals content on the back when clicked.
-
Build a staggered list animation where items animate in one after another as they enter the viewport.
-
Implement a page transition system that animates between different routes in a Vue application.
-
Create a draggable element using GSAP's Draggable plugin and integrate it with Vue's data system.
-
Build an interactive chart that animates when data changes using both GSAP and Vue's reactivity.
By practicing these exercises, you'll gain confidence in combining these powerful technologies to create fluid, engaging animations for your Vue applications.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)