В этой статье вы узнаете, как при помощи CSS создать анимированный шар, движущийся по траектории, напоминающей американские горки. Также, вы узнаете, как работает CSS функция cubic-bezier
, и как объединить несколько простых анимаций, чтобы создать одну сложную.
Мы ежедневно просматриваем веб-страницы, и как разработчики, склонны замечать тонкие детали на веб-сайте. При этом самое заметное, что сильнее всего привлекает внимание, это то, насколько плавны анимации. Анимация отлично подходит для того, чтобы оживить пользовательский интерфейс и дизайн сайта в общем. Так, можно создать интерактивный веб-сайт, который привлечет внимание посетителей и надолго останется у них в памяти.
На первый взгляд кажется, что создание достаточно комплексных анимаций по силам только опытным специалистам. Но хорошая новость заключается в том, что в CSS можно объединять несколько простых анимаций, создавая тем самым более сложную!
В этой статье вы узнаете:
- Что такое кривые Безье, и как их можно использовать для создания "сложной" анимации всего в одной строке CSS;
- Как объединять анимации, чтобы создать более сложную анимацию;
- Как создать анимацию американских горок, используя изученный материал.
Кривая Безье: Что это такое?
Функция cubic-bezier
в CSS - это функция плавности (easing), которая дает вам полный контроль над тем, как ваша анимация будет вести себя с течением времени. Вот официальное определение:
Кубическая Безье - это тип функции плавности, определяемая четырьмя действительными числами, которые задают две контрольные точки
P1
иP2
кубической кривой Безье, конечные точкиP0
иP3
, которые зафиксированы в (0, 0) и (1, 1) соответственно. Координаты по осих
точекP1
иP2
ограничены диапазоном [0, 1].
Но что такое функция плавности?
ДАВАЙТЕ НАЧНЕМ С ЛИНЕЙНОЙ КРИВОЙ
Представьте себе две точки P0
и P1
, где P0
- начальная точка анимации, а P1
- конечная. Теперь представьте другую точку, линейно перемещающуюся между этими двумя точками следующим образом:
Это называется линейной кривой! Это самая простая анимация, и вы, вероятно, использовали ее раньше, когда начинали изучать CSS.
ДАЛЕЕ: КВАДРАТИЧНАЯ КРИВАЯ БЕЗЬЕ
Теперь, представьте, что у вас есть три точки: P0
, P1
и P2
. Вы хотите, чтобы анимация двигалась от точки P0
в точку P2
. В этом случае P1
является контрольной точкой, которая управляет кривой анимации.
Идея квадратичной кривой Безье заключается в следующем:
- Соедините воображаемыми линиями точки
P0
иP1
и точкиP1
иP2
(представлены серыми линиями). - Точка
Q0
перемещается по линии между точкамиP0
иP1
. В то же время точкаQ1
перемещается по линии между точкамиP1
иP2
. - Соедините воображаемой линией точки
Q0
иQ1
(зеленая линия). - В то время, как начинают двигаться точки
Q0
иQ1
, вдоль зеленой линии начинает двигаться точкаB
. Путь, по которому проходит точкаB
, и есть путь анимации.
Обратите внимание, что точки Q1, Q2 и B не движутся с одинаковой скоростью. Их движение должно начинаться одновременно и заканчиваться в одно и то же время. Таким образом, каждая точка движется с соответствующей скоростью в зависимости от длины линии, по которой она движется.
НАКОНЕЦ: КУБИЧЕСКАЯ КРИВАЯ БЕЗЬЕ
Кубическая кривая Безье состоит из 4 точек: P0
, P1
, P2
и P3
. Анимация начинается в точке P0
и заканчивается в точке P3
. Точки P1
и P2
- контрольные.
Кубическая кривая Безье работает следующим образом:
- Нарисуйте воображаемые линии на отрезках (P0, P1), (P1, P2) и (P2, P3). Представлены серыми линиями.
- Точки Q0, Q1 и Q2 перемещаются по линиям (P0, P1), (P1, P2) и (P2, P3) соответственно.
- Нарисуйте воображаемые линии на отрезках (Q0, Q1) и (Q1, Q2). Зеленые линии.
- Точки R0 и R1 перемещаются по линиям (Q0, Q1) и (Q1, Q2) соответственно.
- Нарисуйте линию между точками R0 и R1. Синяя линия.
- Наконец, точка B перемещается вдоль линии, соединяющей точки R0 и R1. Это и есть путь анимации.
Сложение анимаций
Большие анимации с множеством этапов можно разбить на несколько мелких анимаций. Вы можете добиться этого, добавив CSS свойство задержки animation-delay
. Вычислить задержку просто; нужно сложить длительность всех анимаций до той анимации, для которой вы рассчитываете задержку.
Например:
animation: movePointLeft 4s linear forwards, movePointDown 3s linear forwards;
Здесь у нас есть две анимации: movePointLeft
и movePointDown
. Задержка анимации movePointLeft
будет равна нулю, потому что это анимация, которая запускается первой. Задержка же анимации movePointDown
составит четыре секунды, потому что столько длится анимацция movePointLeft
.
Таким образом, мы получаем следующие значения свойства animation-delay
:
animation-delay: 0s, 4s;
Обратите внимание, что если у вас одновременно запускаются две или более анимации, то их задержка будет одинаковой. Кроме того, когда вы рассчитываете задержку для предстоящих анимаций, вы должны рассматривать их как одну анимацию.
Например:
animation: x 4s linear forwards, y 4s linear forwards, jump 2s linear forwards;
Предположим, мы хотим, чтобы анимации x
и y
начинались одновременно. В этом случае задержка для этих двух анимаций будет равна нулю, в то время как задержка для анимации jump
составит четыре секунды (а не восемь!).
animation-delay: 0s, 0s, 4s;
Создание анимации американских горок
Теперь, когда у нас есть все базовые знания, пора применить их на практике!
ПОНИМАНИЕ АНИМАЦИИ
Траектория американских горок состоит из трех частей:
- Скольжение (The sliding part),
- Петля (The loop part),
- И небольшая анимация горизонтального прохода между первыми двумя анимациями и в конце.
ПОДГОТОВКА
Начнем с создания простого шара, который будет символизировать тележку для американских горок.
1. Добавьте следующий код в тело вашего нового HTML файла:
<div id="the-cart" class="cart"></div>
2. Добавьте следующий код в ваш CSS файл:
.cart {
background-color: rgb(100, 210, 128);
height: 50px;
width: 50px;
border: 1px solid black;
border-radius: 50px;
position: absolute;
left: 10vw;
top: 30vh;
}
Чтобы сделать анимацию адаптивной, мы будем использовать единицы ширины (vw
) и высоты (vh
) окна просмотра. Вы же можете использовать любые единицы измерения.
СКОЛЬЖЕНИЕ
Ту часть, в которой наш шар-тележка скользит вниз и вверх, можно реализовать с помощью функции cubic-bezier
! Анимация будет состоять из 2 частей, первая часть - анимация вдоль оси х
, вторая - вдоль оси y
. Анимация по оси х
- это обычная линейная анимация по горизонтали. Определим ее ключевые кадры следующим образом:
@keyframes x {
to {
left: 40vw;
}
}
Добавим ее в свойство animation
в траектории шара:
animation: x 4s linear forwards
Вторая часть анимации скольжения - анимация по оси y
. Именно здесь мы будем использовать функцию cubic-bezier
. Давайте сначала определим ключевые кадры анимации. Мы хотим, чтобы разница между начальной и конечной точками была настолько маленькой, чтобы шар после провала достигал почти той же высоты.
@keyframes y {
to {
top: 29.99vh;
}
}
Теперь подумаем о функции cubic-bezier
. Нам нужно, чтобы сначала шарик медленно двигался вправо, а затем, когда он соскальзывает вниз, покатился быстрее.
- Медленное движение вправо означает, что
P1
будет идти вдоль осиx
. Таким образом, мы получаем позицию(V, 0)
.- Нам нужно выбрать подходящее значение
V
, которое заставит наш шар медленно двигаться вправо, но не слишком далеко, чтобы он не прошел все пространство. В нашем случае значение0.55
подходит лучше всего.
- Нам нужно выбрать подходящее значение
- Для достижения эффекта скольжения вниз нам нужно переместить
P2
вниз по осиy
, т. е. задать отрицательное значение. Таким образом,P2 = (X, -Y)
.Y
должно иметь большое значение. В данном случае мы выбралиY=5000
.- Что касается
X
. Мы знаем, что скорость анимации должна быть выше при скольжении вниз и медленнее при подъеме. Таким образом, чем ближеX
к нулю, тем будет круче угол анимация при скольжении вниз. В данном случае зададимX = 0.8
.
Теперь мы можем задать функцию cubic-bezier
. Она будет cubic-bezier(0.55, 0, 0.2, -800)
.
Давайте добавим ключевые кадры в наше свойство animation
:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -5000) forwards;
Это первая часть нашей анимации, поэтому задержка равна нулю. При этом в любом случае мы должны добавить свойство animation-delay
, так как, последующие анимации браузер будет запускать в другое время, чем начинается первая анимация.
animation-delay: 0s, 0s;
ДОБАВЛЯЕМ ГОРИЗОНТАЛЬНЫЙ ПРОХОД
Перед заходом на петлю шарик должен некоторое время двигаться по горизонтали вперед, чтобы между анимациями образовалось свободное пространство. Итак, давайте сделаем это!
Определим ключевые кадры:
@keyframes x2 {
to {
left: 50vw;
}
}
Добавим это в свойство animation
:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -5000) forwards,
x2 0.5s linear forwards;
Эта анимация должна начинаться после анимации скольжения, а анимация скольжения занимает четыре секунды; таким образом, задержка составит четыре секунды:
animation-delay: 0s, 0s, 4s;
ПЕТЛЯ
Чтобы в CSS создать круг (петлю), нам нужно переместить круг в центр петли и запустить анимацию оттуда. Мы хотим, чтобы радиус окружности был 100px, поэтому мы изменим положение окружности на top: 20vh
(30 - желаемый радиус (здесь 10vh)). Однако это должно произойти после завершения анимации скольжения, поэтому мы создадим другую анимацию с нулевой продолжительностью и добавим подходящую задержку.
Создаем ключевые кадры:
@keyframes pointOfCircle {
to {
top: 20vh;
}
}
Добавляем в список анимаций с продолжительностью 0s:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -5000) forwards,
x2 0.5s linear forwards,
pointOfCircle 0s linear forwards;
Добавляем задержку, которая должна составлять 4.5s:
animation-delay: 0s, 0s, 4s, 4.5s;
Сама петля
Чтобы создать анимацию петли:
Создаем ключевой кадр, который перемещает шар обратно на старое положение, а затем поворачивает его:
@keyframes loop {
from {
transform: rotate(0deg) translateY(10vh) rotate(0deg);
}
to {
transform: rotate(-360deg) translateY(10vh) rotate(360deg);
}
}
Добавляем анимацию в свойство animation
:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -5000) forwards,
x2 0.5s linear forwards,
pointOfCircle 0s linear forwards,
loop 3s linear forwards;
Добавляем задержку, которая также должна составлять 4.5s:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s;
ДОБАВЛЯЕМ ГОРИЗОНТАЛЬНЫЙ ПРОХОД (ЕЩЕ РАЗ)
Ну вот, мы почти и закончили! Нам просто нужно после анимации петли переместить шарик немного вперед по горизонтали, чтобы он не останавливался сразу же после петли.
Добавляем ключевые кадры:
@keyframes x3 {
to {
left: 70vw;
}
}
Добавляем анимацию в свойство animation
:
animation: x 4s linear forwards,
y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards,
x2 0.5s linear forwards,
pointOfCircle 0s linear forwards,
loop 3s linear forwards,
x3 2s linear forwards;
Добавляем подходящую задержку. Здесь она составит 7.5s:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s, 7.5s;
Окончательный результат
Заключение
В этой статье мы рассмотрели, как комбинировать несколько ключевых кадров для создания сложной анимации. Мы также рассмотрели кубические кривые Безье, и как их использовать для создания собственной функции плавности. Мы бы рекомендовали вам продолжать создавать свои сложные анимации, чтобы, как говорится, набить руку. Практика и еще раз практика, и мастерство не заставит себя долго ждать. Хорошего вам дня или ночи!