
В этой статье вы узнаете, как при помощи 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;
Окончательный результат
Заключение
В этой статье мы рассмотрели, как комбинировать несколько ключевых кадров для создания сложной анимации. Мы также рассмотрели кубические кривые Безье, и как их использовать для создания собственной функции плавности. Мы бы рекомендовали вам продолжать создавать свои сложные анимации, чтобы, как говорится, набить руку. Практика и еще раз практика, и мастерство не заставит себя долго ждать. Хорошего вам дня или ночи!