Abr@X@bra.ru
Vue.js + GSAP =  Крутая анимация

Vue.js + GSAP =  Крутая анимация

02.10.2018
797
Vue.js - это структура Javascript, которая одновременно является мощной и простой. С помощью Vue CLI мы можем быстро внедрять новые приложения со всеми последними функциями Webpack, не тратя часы на настройку настройки Webpack. Просто установите Vue CLI, введите vue create <project-name>, и вперед!

GSAP - это библиотека анимации JavaScript, которая позволяет быстро реализовать веб-анимацию в вашем проекте.

При создании сайта (главной страницы) Daily Fire я активно использовал анимацию, пытаясь показать, как работает продукт. Используя GSAP, а не GIF или видео, я смог добавить к слоям интерактивности и анимации, чтобы сделать их более привлекательными. Интеграция GSAP с Vue.js, как вы увидите, проста, но мощна.

Давайте посмотрим, как реализовать простую анимацию с GSAP и Vue. Мы будем использовать .vue-файлы в этой статье, они включаются с помощью Web-загрузчика vue-loader, автоматически доступного для проектов, созданных с помощью Vue CLI.

Основы

Давайте сначала напишем разметку, чтобы получить представление о том, что мы будем анимировать.

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

Сначала мы импортируем TimelineLite из GSAP, а затем, когда компонент монтируется, мы получаем ссылку на наш элемент через $Refs. Затем мы инициализируем шкалу GSAP и воспроизводим анимацию.

  1. Экземпляр timeline предоставляет метод, с помощью которого мы передаем 3 аргумента:

  2. Элемент для анимации

  3. Время для анимации

  4. Объект, описывающий анимацию для выполнения

Здесь мы видим, как выглядит этот небольшой фрагмент кода:




Довольно просто! Но давайте использовать 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>

Хотя сначала это может выглядеть пугающе, но уделите несколько минут, чтобы разобраться, что на самом деле происходит. Все, что есть, - это несколько преобразований CSS, стоящих в очереди последовательно. Обратите внимание, что в нем есть несколько пользовательских настроек. GSAP предлагает интересный инструмент для настройки эффектов анимации: GSAP Ease Visualizer.


Зацикливание

В TimelineLite от GSAP есть атрибут onComplete, который мы можем использовать для анимации. Кроме того, мы предоставляем timeline остальным компонентам.
<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 перезапустит анимацию, когда она будет завершена.

Добавление интерактивности

Теперь у нас есть прочная основа, чтобы начать интегрировать некоторую интерактивность. В качестве примера добавим кнопку для рандомного обновления логотипа.

Для этого нам нужно будет сделать несколько вещей:

  1. Переместим изображения в атрибут данных Vue

  2. Создать массив изображений

  3. Создать метод получения случайного логотипа

  4. Добавить кнопку, чтобы изменить логотип

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


Заключение

Мне хочется думать, что, это было вам интересно! Я надеюсь, что у вас теперь есть несколько идей о том, как добавить немного анимации и интерактивности к вашим собственным сайтам.





Vue.js, GSAP
Читайте также:
Css эффект - разорванный текст

Css эффект - разорванный текст

В данном посте, хочу поделиться, как можно сделать очень интересный эффект - разорванного текста с помощью CSS.
Читать
CSS Grid идеально подходит для адаптивной верстки

CSS Grid идеально подходит для адаптивной верстки

Я думаю, что вы уже в курсе, что Grid превосходит Flexbox для создание макетов. Но как насчет адаптивных макетов? Что лу...
Читать
Canvas – HTML5. Подробное руководство

Canvas – HTML5. Подробное руководство

Canvas с его обманчиво простым API может революционно преобразовать создание веб-приложений для всех устройств, а не тол...
Читать