Skip to main content

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:

bash
npm install gsap

Or if you're using Yarn:

bash
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:

html
<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:

html
<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's ref attribute
  • In the mounted lifecycle hook, we use GSAP's to 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:

html
<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:

html
<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:

html
<script>
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

// Register the plugin
gsap.registerPlugin(ScrollTrigger)
</script>

Then create a scroll-triggered animation:

html
<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:

html
<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:

html
<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:

html
<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:

  1. Use object pooling: For repetitive animations, reuse the same objects rather than creating new ones.

  2. Be mindful of watchers: When animating based on reactive data changes, use debouncing or throttling for frequently changing values.

  3. Use the will-change property: For complex animations, add the CSS will-change property to elements that will be animated.

css
.animated-element {
will-change: transform, opacity;
}
  1. 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:

javascript
// 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:

  1. Official GSAP Documentation
  2. GSAP Easing Visualizer
  3. Vue.js Animation Guide

Exercises

  1. Create a card flip animation using GSAP and Vue that reveals content on the back when clicked.

  2. Build a staggered list animation where items animate in one after another as they enter the viewport.

  3. Implement a page transition system that animates between different routes in a Vue application.

  4. Create a draggable element using GSAP's Draggable plugin and integrate it with Vue's data system.

  5. 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! :)