Практика: создание CSS-анимации
Добро пожаловать на заключительный урок данного раздела! Сегодня мы будем применять полученные знания на практике, а именно учиться трансформировать элементы, связывать эти трансформации с анимацией и создавать красивые эффекты, пользуясь возможностями CSS3.
Задание
Помните нашу предыдущую практику, где мы создавали веб-страничку для музыкальной группы? Мы останемся верны этой тематике и создадим интерактивную карту с отметками, в каких городах музыкальная группа планирует проводить концерт. При наведении курсора на точку города будет появляться выноска с датой мероприятия и кнопкой «Купить билеты»:

Загрузка файлов
Вам понадобятся определенные файлы для выполнения задания. Скачайте архив на компьютер и ознакомьтесь с его содержимым. Чтобы не тратить время на написание кода, который не относится напрямую к теме этого урока, мы заранее подготовили для вас HTML-разметку и базовые стили CSS. Вам понадобится добавить только те стили, которые будут касаться анимированных объектов.
План работы
- Для четырех точек на карте (города, в которых будут проходить концерты) создать пульсирующую анимацию для привлечения внимания.
- При наведении курсора на точку города анимация должна становиться на паузу. Когда курсор убран, анимация возобновляется.
- Также при наведении курсора на точку города должна плавно появляться небольшая выноска с местом и датой концерта, кнопкой для покупки билетов. Когда курсор убран, информационная выноска исчезает.
- Цвет кнопки в выноске должен меняться при наведении курсора.
Примечание: в целях экономии места мы не записываем в обучающем уроке префиксы производителей. Но помните, что на реальных проектах их нужно использовать.
1. Анимация для отметок на карте
Откройте в браузере веб-страницу из скачанного архива. Перед вами блок с картой, на которой нанесено четыре отметки с названиями городов. Наша задача — создать эффект расходящихся волн вокруг каждой точки. Мы сделаем две волны, в роли которых будут выступать псевдоэлементы :before и :after:

Псевдоэлементы удобно использовать, когда требуется добавить какое-то украшение к основному элементу. Это избавляет от необходимости добавлять лишний HTML-код, который не несет особого смысла.
Откройте в редакторе кода документ style.css из папки css. В течение урока мы будем соблюдать порядок в таблице стилей, добавляя новые правила не просто в конец документа, а размещая их там, где это будет логично. Поэтому найдите селектор .pin .popover и добавьте над ним следующие стили для псевдоэлементов элемента .pin:
.pin:before,
.pin:after {
content: '';
position: absolute;
left: 50%;
top: 50%;
display: block;
border-radius: 50%;
border: 1px solid #f3244a;
width: 0;
height: 0;
margin-left: -2px;
margin-top: -2px;
}
Мы не добавляем никакой контент к этим псевдоэлементам, а только создаем пустой блок с рамкой и скругленными углами, чтобы в итоге получить кольцо.
В начальном виде ширина и высота псевдоэлементов равна нулю. И с помощью анимации мы увеличим их размеры, чтобы создать эффект расходящихся волн. Для этого понадобится создать ключевые кадры для каждой волны.
Найдите в начале таблицы стилей комментарий /* Keyframes */ и запишите под ним два следующих правила @keyframes:
@keyframes pinBeforeWave {
from {
width: 0;
height: 0;
margin-left: -2px;
margin-top: -2px;
}
to {
width: 40px;
height: 40px;
margin-left: -21px;
margin-top: -21px;
opacity: 0;
}
}
@keyframes pinAfterWave {
from {
width: 0;
height: 0;
margin-left: -2px;
margin-top: -2px;
}
to {
width: 66px;
height: 66px;
margin-left: -34px;
margin-top: -34px;
opacity: 0;
}
}
Обе анимации имеют одинаковое начало, но отличаются окончанием. Анимацию pinBeforeWave мы применим к псевдоэлементу :before, и в процессе ее выполнения он увеличится до размеров 40×40 пикселей (маленькая волна). Анимация pinAfterWave предназначена для псевдоэлемента :after, к концу которой он примет размеры 66×66 пикселей (большая волна).
Кроме этого, в обеих анимациях предусмотрено смещение элементов на определенное количество пикселей влево и вверх — это нужно для того, чтобы при увеличении кольца отметка города визуально оставалась в его центре. И, наконец, свойство opacity в последнем ключевом кадре означает то, что обе волны будут плавно исчезать в процессе своего расширения.
Давайте применим созданные анимации к псевдоэлементам. Для этого добавьте следующий код, разместив его следом под стилем для селектора .pin:before, .pin:after:
.pin:before {
animation: pinBeforeWave 1s ease-in infinite;
}
.pin:after {
animation: pinAfterWave 1s ease-in infinite;
}
Обе анимации будут длиться одну секунду. Распределение скорости анимации в течение этой секунды будет происходить по функции ease-in. Анимация будет повторяться бесконечно.
Сохраните изменения в таблице стилей и обновите страницу в браузере. Анимация вокруг отметок уже работает, и нам пора переходить к следующему пункту плана.
2. Пауза анимации при наведении курсора
Когда пользователь наводит курсор на элемент .pin, анимация псевдоэлементов должна становиться на паузу. CSS позволяет применять стили к дочерним элементам, когда на их родителя наведен курсор. То же самое работает и с псевдоэлементами. Добавьте этот стиль под предыдущим:
.pin:hover:before,
.pin:hover:after {
animation-play-state: paused;
}
Данный код говорит: когда на элемент .pin наведен курсор (состояние :hover), нужно поставить на паузу анимацию псевдоэлементов :before и :after.
3. Появление выноски
При наведении курсора на отметку должно происходить еще одно действие, а именно появление выноски с информацией о концерте. В изначальном состоянии все выноски скрыты от глаз посетителя с помощью свойств visibility: hidden и opacity: 0.
Найдите в файле CSS селектор .pin .popover:before и добавьте следом за ним следующий стиль:
.pin:hover .popover {
visibility: visible;
opacity: 1;
}
У вас мог возникнуть вопрос, зачем мы скрыли выноску сразу двумя способами. Дело в том, что использования лишь одного из этих свойств будет недостаточно. Если убрать свойство visibility и оставить только opacity: 0, то элемент не будет по-настоящему скрыт: да, он не будет виден для глаз, но его увидит скринридер, что иногда может мешать.
Если же убрать свойство прозрачности и оставить только visibility: hidden, то мы не сможем добиться плавности при появлении элемента, поскольку свойство transition не действует на свойство visibility. Именно поэтому мы использовали сразу два свойства для скрытия выноски.
Кстати о плавности. Если вы сейчас обновите страницу и наведете курсор на точку, то увидите, что выноска появляется, но делает это резко. Настало время обратиться к свойству transition. Найдите селектор .pin .popover и добавьте к нему такую строку:
transition: all 0.2s ease-in-out;
Теперь выноска появляется плавно: свойство opacity переходит от значения 0 к значению 1 за 200 миллисекунд, а скорость движения анимации соответствует функции ease-in-out.
Идем дальше. Когда мы рассказывали о свойстве transition-delay, то упоминали о том, что его удобно применять для небольшой задержки выпадающего меню перед его исчезновением, чтобы пользователь успевал навести курсор на ссылку меню. Не лишним будет применить этот эффект и для выноски, чтобы она исчезала с легкой задержкой. Для этого добавьте еще одно значение к свойству transition для селектора .pin .popover — 0.5s перед точкой с запятой:
transition: all 0.2s ease-in-out 0.5s;
Но это еще не всё. Сейчас задержка появления выноски срабатывает в обоих направлениях — когда курсор наводится и когда отводится. Чтобы оставить задержку только для второго случая, допишите следующую строку к селектору .pin:hover .popover:
transition-delay: 0s;
Сохраните изменения и обновите страницу в браузере. Теперь всё работает правильно: выноска появляется плавно и без задержки, а исчезает так же плавно, но с задержкой в полсекунды.
Нам осталось поработать еще над одной деталью. На этот раз мы вспомним свойство transform и его функцию вращения rotate, чтобы добавить еще один визуальный эффект при появлении выноски. Она будет словно разворачиваться лицом к зрителю в процессе появления, а затем так же исчезать.
В состоянии невидимости выноска будет развернута на 90 градусов по оси Y. Допишите следующий стиль к селектору .pin .popover:
transform: rotateY(90deg);
При наведении курсора на точку города выноска должна возвращаться в свое нормальное положение. Для этого добавьте строку ниже к стилю для селектора .pin:hover .popover:
transform: rotateY(0deg);
Сохранитесь и обновите веб-страницу. Понаблюдайте теперь за поведением выносок: они появляются плавно и с эффектом разворота, напоминая карточки.
4. Цвет кнопки в выноске
Последний пункт плана — плавное изменение цвета кнопки в выноске при наведении курсора на нее. Для начала создадим стиль для кнопки в состоянии :hover. Найдите селектор .pin .popover .button и запишите под ним следующий код:
.pin .popover .button:hover {
background-color: #e10087;
}
И, наконец, чтобы переход от начального цвета к конечному происходил плавно, добавьте эту строку к стилю селектора .pin .popover .button:
transition: all 0.2s ease-in-out;
Снова сохраните изменения и полюбуйтесь результатом.
Завершение
Поздравляем! Вы полностью прошли еще один раздел учебника и создали интерактивную карту. Как и всегда, в случае каких-либо проблем вы можете посмотреть готовый рабочий код, который лежит в архиве вместе с другими файлами. А вот и демо нашего урока:
Рекомендуем вам дополнительно потренироваться в использовании CSS-анимации: придумайте альтернативные эффекты и трансформации для выносок и отметок либо попробуйте создать анимацию на других веб-страницах. Как видите, это очень увлекательная тема!
Когда вы будете готовы, приглашаем перейти к следующему разделу нашей книги, который посвящен стилизации таблиц и веб-форм. В первом уроке мы поговорим о том, как писать CSS для HTML-таблиц.