GSAP - это библиотека анимации JavaScript, которая позволяет быстро реализовать веб-анимацию в вашем проекте.
При создании сайта (главной страницы) Daily Fire я активно использовал анимацию, пытаясь показать, как работает продукт. Используя GSAP, а не GIF или видео, я смог добавить к слоям интерактивности и анимации, чтобы сделать их более привлекательными. Интеграция GSAP с Vue.js, как вы увидите, проста, но мощна.<template>
<div ref="box" class="box"></div>
</template>
<style>
.box {
height: 60px;
width: 60px;
background: red;
}
</style>
Здесь мы определяем div с классом box и задаем ему размер и красный цвет. Обратите внимание на тег ref в div, мы будем ссылаться на этот элемент при работе с GSAP.
Теперь давайте подключим GSAP
<template>
<div ref="box" class="box"></div>
</template>
<script>
import { TimelineLite } from 'gsap'
export default {
mounted() {
const { box } = this.$refs
const timeline = new TimelineLite()
timeline.to(box, 1, { x: 200, rotation: 90 })
}
}
</script>
<style>
/* styles emitted */
</style>
Экземпляр timeline предоставляет метод, с помощью которого мы передаем 3 аргумента:
Элемент для анимации
Время для анимации
Здесь мы видим, как выглядит этот небольшой фрагмент кода:
Довольно просто! Но давайте использовать EasePack от GSAP, чтобы дать этой небольшой анимации немного больше жизни. Давайте поменяем цвет квадрата во время анимации.
<template>
<div ref="box" class="box"></div>
</template>
<script>
import { TimelineLite, Back } from 'gsap'
export default {
mounted() {
const { box } = this.$refs
const timeline = new TimelineLite()
timeline.to(box, 1, {
x: 200,
rotation: 90,
ease: Back.easeInOut, // Specify an ease
})
timeline.to(box, 0.5, {
background: 'green'
},
'-=0.5' // Run the animation 0.5s early
)
}
}
</script>
<style>
/* styles emitted */
</style>
Обратите внимание на дополнительный аргумент -=0.5, здесь мы можем указать GSAP, чтобы запустить анимацию относительно завершения предыдущей. Используйте + =, чтобы указать время после завершения, и - = указать время до завершения.
С этим простым дополнением мы сделали нашу анимацию намного более живой!
При базовом понимании этих принципов мы можем начать создавать более сложные, привлекательные анимации. Как мы увидим в следующем примере, это действительно просто!
Давайте начнем с разметки:
<template>
<div class="bubble-wrapper">
<div ref="bubble" class="bubble">
<img class="bubble-image"
src="./assets/img/slack-white.svg" />
</div>
<div ref="bubblePulse" class="bubble-pulse"></div>
</div>
</template>
<style>
.bubble-wrapper {
position: relative;
}
.bubble {
position: relative;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid white;
background: #272727;
border-radius: 50%;
height: 100px;
width: 100px;
}
.bubble-pulse {
position: absolute;
z-index: 1;
height: 120px;
width: 120px;
top: 50%;
left: 50%;
margin-top: -60px;
margin-left: -60px;
background: #272727;
border-radius: 50%;
opacity: 0;
transform: scale(0);
}
.bubble-image {
height: 50%;
}
</style>
Теперь дадим этому изображению немного жизни!
<template>
<!-- HTML emitted -->
</template>
<script>
import { TimelineLite, Back, Elastic, Expo } from "gsap"
export default {
mounted() {
const { bubble, bubblePulse } = this.$refs
const timeline = new TimelineLite()
timeline.to(bubble, 0.4, {
scale: 0.8,
rotation: 16,
ease: Back.easeOut.config(1.7),
})
timeline.to(
bubblePulse,
0.5,
{
scale: 0.9,
opacity: 1,
},
'-=0.6'
)
this.timeline.to(bubble, 1.2, {
scale: 1,
rotation: '-=16',
ease: Elastic.easeOut.config(2.5, 0.5),
})
this.timeline.to(
bubblePulse,
1.1,
{
scale: 3,
opacity: 0,
ease: Expo.easeOut,
},
'-=1.2'
)
}
}
</script>
<style>
/* CSS Emitted */
</style>
<template>
<!-- HTML Emitted -->
</template>
<script>
// ...
export default {
data() {
return {
timeline: null,
}
},
mounted() {
// ...
this.timeline = new TimelineLite({
onComplete: () => this.timeline.restart()
})
// ...
}
}
</script>
<style>
/* CSS Emitted */
</style>
Теперь GSAP перезапустит анимацию, когда она будет завершена.
Переместим изображения в атрибут данных Vue
Создать массив изображений
Создать метод получения случайного логотипа
Добавить кнопку, чтобы изменить логотип
<template>
<div class="bubble-wrapper">
<div ref="bubble" class="bubble">
<img class="bubble-image"
:src="currentLogo" />
</div>
<div ref="bubblePulse" class="bubble-pulse"></div>
</div>
<button @click="randomiseLogo">Random Logo</button>
</template>
<script>
// ...
export default {
data() {
return {
timeline: null,
logos: ['path/to/logo-1.svg', 'path/to/logo-2.svg', 'path/to/logo-3.svg'],
currentLogo: '',
}
},
methods: {
randomiseLogo() {
const logosToSample = this.logos.filter(logo => logo !== this.currentLogo)
this.currentLogo = logosToSample[Math.floor(Math.random() * logosToSample.length)]
}
},
mounted() {
this.randomiseLogo()
// ...
}
}
</script>
<style>
/* CSS Emitted */
</style>
Мы могли бы даже использовать нашу функцию onComplete, чтобы получить случайный логотип, когда сбрасывается анимация:
<template>
<!-- HTML Emitted -->
</template>
<script>
// ...
export default {
// ...
methods: {
randomiseLogo() {
const logosToSample = this.logos.filter(logo => logo !== this.currentLogo)
this.currentLogo = logosToSample[Math.floor(Math.random() * logosToSample.length)]
}
},
mounted() {
this.randomiseLogo()
this.timeline = new TimelineLite({
onComplete: () => {
this.randomiseLogo()
this.timeline.restart()
}
});
// ...
}
}
</script>
<style>
/* CSS Emitted */
</style>