Анимация SVG с помощью CSS

На сегодняшний день существует уже не один способ создавать SVG анимацию. Это можно сделать с помощью тега , который вставляется прямо в код SVG. Есть специальные библиотеки, такие как Snap.svg или SVG.js.

Мы рассмотрим немного другой подход: с помощью встроенного SVG (SVG кода прямо в HTML) и анимации отдельных частей прямо через CSS.

Я недавно поэкспериментировал с этим методом, в проекте для моей альма-матер Wufoo, так, чтобы немного освежить в памяти тему, которую мы будем здесь рассматривать.

В моих последних проектах SVG использовались редко, поэтому, думаю, эта статья представляет собой прекрасную возможность уделить ему больше внимания.

Окончательный вид анимации очень простой. Вот как она выглядит:

Посмотреть на CodePen

Давайте рассмотрим, как это делается.

1. Составляем список элементов, которые мы будем использовать

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

Мой план заключался в том, чтобы сделать супер простую рекламу Wufoo, использовав их классический логотип, цвета и корпоративный стиль. А затем добавить немного креатива:

  1. Создать эффект, будто буквы убегают со страницы. Wufoo - это веселое слово, пусть буквы тоже будут веселыми;
  2. За день до этого мы разработали дизайн футболки, на лицевой стороне которой был изображен динозавр, а на задней надпись: «Быстрый. Умный. Грозный». Это черты, которые присущи и динозаврам, и Wufoo. Не говоря уже о том, что мы обыграли слово «FORMidble» (грозный). Поэтому я захотел сделать так, чтобы в анимационном блоке появлялись и исчезали эти слова;
  3. Чтобы связать эти слова с динозавром, у нас будет появляться голова T-Рекса, а затем быстро исчезать. При этом будет выводиться слово «Быстрый», что будет еще одним интересным связующим звеном для элементов.
  4. Все эти элементы я загрузил в Illustrator:
Составляем список элементов, которые мы будем использовать

Обратите внимание, как очерчены тексты логотипа и слогана. Это означает, что они являются просто векторными фигурами, и к ним легко можно применять эффекты, как в SVG, так и в <path>.

Текст, который вы видите, «Быстрый.» так и остается в Illustrator в формате текста.

Когда я сохраню файл в Illustrator, надпись останется элементом .

2. Сохраняем в формате SVG

Illustrator поддерживает функцию сохранения в формате SVG:

Сохраняем в формате SVG

Вы можете открыть этот SVG-файл в редакторе кода и увидеть в нем код SVG:

Сохраняем в формате SVG - 2

3. Вычищаем SVG, задаем классы для фигур

Вы можете пропустить код через SVGO, чтобы оптимизировать его и убрать ненужные элементы типа DOCTYPE и тому подобное.

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

4. Вставляем SVG

Вы можете скопировать этот SVG-код и вставить его прямо в HTML, в то место, где вы хотите выводить блок. Но это всего лишь примитивный шаблон.

Вы можете сделать что-то вроде этого:

<div class="module module-ad">

   </div>

   ...

5. Анимация!

Теперь все эти фигуры загнаны в DOM, и мы можем позиционировать их и задавать стили, как и для любого другого элемента HTML. Давайте сделаем это.

Предположим, мы хотим использовать 10-секундную временную шкалу:

Сначала выпадают и исчезают слова

Первое, что мы хотим сделать, это вывести поочередно слова «Быстрый. Умный. Грозный.» Каждое слово будет показываться в течение одной секунды.

Так мы создаем анимацию, в которой показ каждого слова занимает 10% времени:

@keyframes hideshow {
  0% { opacity: 1; }
  10% { opacity: 1; }
  15% { opacity: 0; }
  100% { opacity: 0; }
}

Затем указываем первое слово и длительность всей анимации в 10 секунд (10% из которых составляет 1 секунда):

.text-1 {
  animation: hideshow 10s ease infinite;
}

Следующие два слова сначала будут скрытыми (opacity: 0;), а затем используем ту же анимацию, только с задержкой во времени, чтобы следующие слова выводились немного позже:

.text-2 {
  opacity: 0;
  animation: hideshow 10s 1.5s ease infinite;
}
.text-3 {
  opacity: 0;
  animation: hideshow 10s 3s ease infinite;
}

Дополнительные 0,5 секунды нужны для того, чтобы задать интервал между выводом каждого следующего слова.

Прыгающие буквы

Как только мы задали анимацию для этого элемента, приступаем к эффектам для букв в слове Wufoo, которые должны прыгать в сторону вот так:

Прыгающие буквы

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

Таким образом, он будет соответствовать нашему 10-секундному графику, и располагаться посередине временной шкалы. Нам остается только задать параметры для прокручивания эффекта анимации в одном направлении, потому что при обратной прокрутке он просто вернется на исходную позицию.

Эффекты для каждой буквы имеют небольшую задержку во времени, поэтому они перемещаются не все одновременно, а одна за другой:

.wufoo-letter {
  animation: kaboom 5s ease alternate infinite;
  &:nth-child(2) {
    animation-delay: 0.1s;
  }
  &:nth-child(3) {
    animation-delay: 0.2s;
  }
  &:nth-child(4) {
    animation-delay: 0.3s;
  }
  &:nth-child(5) {
    animation-delay: 0.4s;
  }
}
@keyframes kaboom {
  90% {
    transform: scale(1.0);
  }
  100% {
    transform: scale(1.1);
  }
}

Приведенный выше SCSS-код - это просто короткая версия, он не включает в себя префиксов (которые понадобятся вам на практике).

Я думаю, что animation-delay это свойство, которое было бы полезно взять из оригинального CSS. Это выглядело бы более аккуратно, когда буквы сдвигаются с небольшой задержкой.

И наконец, динозавр

После того, как в блоке промелькнули эти надписи, снизу выезжает голова динозавра. Несмотря на то, что фигура динозавра состоит из большого количества элементов , мы можем позиционировать их все вместе с помощью тега позиционирования (группа), который содержит в себе все эти элементы.

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

@keyframes popup {
  0% {
    transform: translateY(150px);
  }
  34% {
    transform: translateY(20px);
  }
  37% {
    transform: translateY(150px);
  }
  100% {
    transform: translateY(150px);
  }
}

Мы хотим, чтобы этот фрагмент анимации выводился в «последние» приблизительно 3 секунды. Этот цикл на самом деле работает все 10 секунд, но собственно видимые эффекты вы будете наблюдать в течение последних 3 секунд.

Когда translateY (150 пикселей) применен в эффекте, динозавр перемещается так далеко вниз вне поля блока, что вы его не видите.

Но в течение 37% времени этой анимации (около 3 секунд) вы видите, что он медленно двигается вверх, а затем быстро убирается вниз.

Когда мы применим эту анимацию, мы убедимся что:

  • Динозавр сначала скрыт;
  • Вывод этого фрагмента анимации задерживается во времени, так что он начинается сразу после того, как буквы в слове логотипа закончили свой пляс (совершили смешение в сторону и вернулись на место).
.trex {
  transform: translateY(150px);
  animation: popup 10s 6.5s ease infinite;
}

Динозавр падает вниз как раз в последнюю секунду так, чтобы сразу после этого в блоке снова появилось слово «Быстрый» (интервал воспроизведения анимации установлен на infinite, чтобы она запускалась по кругу снова и снова). Это привносит немного веселой синергии.

6. Делаем блок кликабельным / интерактивным объявлением

Одной из полезных особенностей SVG является возможность масштабировать объекты до любого размера без потери качества.

Чтобы создать встроенный блок SVG с сохранением оригинального качества изображений, мы можем использовать технику ol' padded box.

<div class="wufoo-ad-wrap">

     ...

</div>
.wufoo-ad-wrap {
  height: 0;
  padding-top: 100%;
  position: relative;
}
.wufoo-ad {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Идея заключается в том, что «обертка» всегда будет принимать форму квадрата, отталкиваясь от значения его ширины. Затем мы задаем абсолютные значения позиции SVG внутри этого идеального квадрата, размеры которого подгоняются, исходя из ширины.

Поскольку это объявление (которое, конечно, должно быть кликабельным), то в качестве содержащего контейнера вместо <div>, вы можете использовать <a href="">, просто убедитесь, что вы установите его в качестве display: block;.

Мысли напоследок, для справки.

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