Кривые Безье
16.11.2025 • math, svg, css
Линейная анимация значений
Довольно часто нужно сделать плавный переход между одним значением и другим. Это может быть точка в пространстве, скорость перемещения, поворота и многое другое. Чтобы не было резкого рывка, делают переход в течение времени. Самый простой вариант этого — линейный переход, его можно описать формулой
result = tГде t принимает значения от 0 до 1. При увеличении t от 0 до 1 итоговое значение будет также увеличиваться от 0 до 1. Это частный случай описания перехода из одного состояния в другое. Он является одномерным, опирается на то, что начальное значение должно выходить из 0, а конечное быть в 1. Подобный подход часто используется для описания анимаций CSS (и не только в CSS).
Как описать переход от одного местоположения к другому? Возьмём, для примера, перемещение вдоль оси X, и во время анимации будет происходить перемещение от 100 до 200. В нулевой момент времени должна быть позиция 100. В конечный момент — 200. Опишем это всё формулой
x = 100 * (1 - t) + 200 * tНетрудно заметить, что в данном случае мы разбили итоговое положение на сумму из двух, каждое из которых зависит от времени и только от одной точки. При стандартном течении времени первое слагаемое будет иметь значение от 100 до 0, а второе слагаемое — от 0 до 200. Слагаемые будут изменяться линейно.
Немного параметризуем:
x = x0 * (1 - t) + x1 * tГде x0 и x1 — начальная и конечная точки соответственно.
Как описать движение по двум координатам сразу? Можно использовать простой подход и описать движение по каждой оси независимо:
x = x0 * (1 - t) + x1 * t
y = y0 * (1 - t) + y1 * tАнимация с помощью кривых
Довольно быстро можно обнаружить, что подобный подход для анимации приведёт неестественному движению.
Элемент находится в покое, а затем мгновенно получает некую скорость, что контрастирует с поведением в реальном мире. Обычно объекты постепенно набирают скорость, а затем постепенно останавливаются:
Аналогичную проблему можно наблюдать и при переходах между анимациями, когда элемент движется в одном направлении, а затем резко меняет направление движения. Обе проблемы можно решать с помощью плавных переходов, заданных с помощью кривых. Кривые бывают разных видов, а в данной статье мы рассмотрим один из них.
Кривые Безье
Кривые Безье позволяют задавать конкретную форму линий с помощью одной или нескольких вспомогательных точек. В веб-разработке встречаются кубические и, изредка, квадратические кривые Безье.
Уравнение выглядит следующим образом:
result = (1 - t) ^ 3 * P0 + 3 * t * (1 - t) ^ 2 * P1 + 3 * t ^ 2 * (1 - t) * P2 + t * 3 * P3В данном уравнении P0 и P3 — начальная и конечная точка соответственно, а P1 и P2 — вспомогательные точки.
Вспомогательные точки можно видеть во всевозможных графических редакторах:

В CSS чаще всего кривые Безье используется в качестве функции времени в свойствах transition-timing-function / animation-timing-function. Подобные кривые задаются в пределах времени от 0 до 1 (как можно было видеть выше). В случае задания этих свойств через кривую Безье, её начальная точка должна быть в координатах (0, 0), а конечная — (1, 1). Ещё одно ограничение — вспомогательные точки не должны выходить за пределы отрезка [0, 1] по оси X. Чаще всего эти свойства задают в виде предустановленных значений, к примеру, ease-in-out. Данное значение является сокращением для cubic-bezier(0.42, 0, 0.58, 1.0), то есть промежуточные точки заданы в координатах (0.42, 0) и (0.58, 1.0).
Интересный момент анимаций в CSS в том, что значение в процессе может выходить за границы [0, 1]. С помощью данного подхода можно получить эффект “пружины” или “отскока”.
Другой часто встречающийся пример — описание кривых в SVG, а также в CSS свойствах offset-path, clip-path (как в path, так и в shape).
Описание формата в этих свойствах стоит рассказать отдельно, а пока остановимся на этом)