Интеграция с библиотеками анимаций

Vue.js предоставляет мощные встроенные возможности для работы с анимациями через директивы v-bind:class, v-show, v-if и компонент <transition>. Однако для создания сложных и кастомизированных визуальных эффектов часто используется интеграция с внешними библиотеками анимаций, такими как GSAP (GreenSock Animation Platform), Anime.js, Velocity.js и CSS-фреймворки типа Animate.css. Интеграция позволяет сочетать реактивность Vue с гибкостью внешних инструментов.


Использование компонента <transition> с внешними библиотеками

Компонент <transition> является ключевым инструментом для анимации при добавлении и удалении элементов. При интеграции с библиотеками анимаций можно использовать хуки жизненного цикла:

  • before-enter
  • enter
  • after-enter
  • enter-cancelled
  • before-leave
  • leave
  • after-leave
  • leave-cancelled

Пример использования GSAP для анимации появления элемента:

<template>
  <transition
    @enter="enterAnimation"
    @leave="leaveAnimation"
  >
    <div v-if="visible" class="box"></div>
  </transition>
</template>

<script>
import { gsap } from "gsap";

export default {
  data() {
    return { visible: true };
  },
  methods: {
    enterAnimation(el, done) {
      gsap.fromTo(el, { opacity: 0, y: -50 }, { opacity: 1, y: 0, duration: 0.5, onComplete: done });
    },
    leaveAnimation(el, done) {
      gsap.to(el, { opacity: 0, y: 50, duration: 0.5, onComplete: done });
    }
  }
}
</script>

<style>
.box {
  width: 100px;
  height: 100px;
  background-color: #42b983;
}
</style>

Ключевой момент: функция done должна вызываться после завершения анимации, иначе Vue не завершит процесс изменения DOM.


Анимация списков с <transition-group>

Для анимации динамических списков используется компонент <transition-group>. Он поддерживает как встроенные CSS-анимации, так и библиотеки JS-анимаций.

Пример с Anime.js:

<template>
  <transition-group name="list" tag="ul" @before-enter="beforeEnter" @enter="enter">
    <li v-for="item in items" :key="item.id">{{ item.text }}</li>
  </transition-group>
</template>

<script>
import anime from 'animejs/lib/anime.es.js';

export default {
  data() {
    return { items: [{ id: 1, text: 'Первый' }, { id: 2, text: 'Второй' }] };
  },
  methods: {
    beforeEnter(el) {
      el.style.opacity = 0;
      el.style.transform = 'translateY(-20px)';
    },
    enter(el, done) {
      anime({
        targets: el,
        opacity: 1,
        translateY: 0,
        duration: 500,
        easing: 'easeOutExpo',
        complete: done
      });
    }
  }
}
</script>

Особенность: <transition-group> требует уникального key для каждого элемента, иначе анимация работать не будет.


Интеграция с CSS-анимациями

Использование готовых CSS-библиотек, таких как Animate.css, позволяет ускорить процесс без написания JS-кода. Для этого достаточно назначить классы анимации через директивы Vue:

<template>
  <transition name="animate__fadeIn">
    <div v-if="show" class="box"></div>
  </transition>
</template>

<script>
export default {
  data() {
    return { show: true };
  }
}
</script>

<style>
@import "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css";

.box {
  width: 100px;
  height: 100px;
  background-color: #42b983;
}
</style>

Принцип работы: Vue автоматически добавляет и убирает классы *-enter-active, *-leave-active, что позволяет CSS-анимациям запускаться синхронно с изменением DOM.


Использование директив для кастомной анимации

Для повторного использования анимаций удобно создавать кастомные директивы Vue. Например, директива для GSAP:

// directives/gsap.js
import { gsap } from "gsap";

export default {
  mounted(el, binding) {
    gsap.from(el, { opacity: 0, y: binding.value?.y || 50, duration: binding.value?.duration || 0.5 });
  }
}

// main.js
import { createApp } from 'vue';
import App from './App.vue';
import gsapDirective from './directives/gsap';

const app = createApp(App);
app.directive('gsap', gsapDirective);
app.mount('#app');

Использование:

<div v-gsap="{ y: 30, duration: 1 }">Анимированный блок</div>

Преимущество: директива инкапсулирует анимацию и позволяет применять её к любым элементам без повторного кода.


Управление производительностью

При работе с большими списками или сложными анимациями следует учитывать следующие моменты:

  • Использовать requestAnimationFrame или встроенные методы библиотек, чтобы избежать блокировки рендеринга.
  • Минимизировать количество одновременно анимируемых элементов.
  • Отдавать предпочтение GPU-анимируемым свойствам (transform, opacity) вместо width или height.
  • Для мобильных устройств проверять плавность и корректность CSS-анимаций.

Совместное использование нескольких библиотек

Vue позволяет комбинировать библиотеки для различных задач:

  • GSAP — для сложных временных линий и 3D-анимаций.
  • Anime.js — для анимации атрибутов SVG и последовательностей.
  • Animate.css — для стандартных эффектов входа/выхода.
  • Velocity.js — для анимации DOM-элементов при высоких нагрузках.

Комбинация библиотек реализуется через хуки <transition> и <transition-group> либо кастомные директивы. Важно следить за конфликтами классов и таймингов, чтобы не нарушать реактивность Vue.


Реактивные анимации

Vue позволяет связывать анимации с реактивными данными, что открывает возможности создания динамических эффектов, зависящих от состояния приложения:

<template>
  <div :class="animationClass">Контент</div>
</template>

<script>
export default {
  data() {
    return { isActive: false };
  },
  computed: {
    animationClass() {
      return this.isActive ? 'fade-in' : 'fade-out';
    }
  }
}
</script>

<style>
.fade-in {
  animation: fadeIn 0.5s forwards;
}
.fade-out {
  animation: fadeOut 0.5s forwards;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
</style>

Эта методика позволяет синхронизировать визуальные эффекты с логикой приложения, что особенно полезно для динамических интерфейсов, модальных окон и уведомлений.