Анимация путей

Snap.svg предоставляет мощный инструментарий для работы с векторной графикой и анимациями на основе SVG. Анимация путей является одной из ключевых возможностей библиотеки, позволяя создавать плавное движение объектов вдоль кривых и сложных форм.

Работа с элементами пути

Элемент пути (<path>) в Snap.svg создаётся с помощью метода paper.path(), где paper — это экземпляр SVG-контейнера:

var s = Snap(800, 600);
var path = s.path("M50,150 C150,50 350,250 450,150");
  • M — начальная точка (move to)
  • C — кубическая кривизна Безье с контрольными точками

Путь хранит данные в виде строки d, которая определяет все координаты и сегменты кривой.

Анимация объектов вдоль пути

Для перемещения объекта по пути используется метод Snap.animate(). Основная идея заключается в анимации позиции объекта на кривой через длину пути. Snap.svg предоставляет методы getPointAtLength() и getTotalLength() для точного расчёта координат:

var circle = s.circle(0, 0, 20).attr({fill: "#f00"});
var length = path.getTotalLength();

Snap.animate(0, length, function(step) {
    var point = path.getPointAtLength(step);
    circle.attr({cx: point.x, cy: point.y});
}, 2000, mina.easeinout);
  • length — общая длина пути
  • step — текущая позиция вдоль пути
  • point — объект с координатами x и y и углом alpha

Ключевой момент: для плавного движения необходимо использовать подходящие функции интерполяции, такие как mina.linear, mina.easein, mina.easeout или mina.easeinout.

Вращение объекта вдоль кривой

Чтобы объект не только следовал за кривой, но и ориентировался в направлении пути, используется угол alpha, возвращаемый методом getPointAtLength():

Snap.animate(0, length, function(step) {
    var point = path.getPointAtLength(step);
    circle.attr({
        cx: point.x,
        cy: point.y,
        transform: "rotate(" + point.alpha + "," + point.x + "," + point.y + ")"
    });
}, 2000, mina.easeinout);
  • transform применяет вращение относительно центра объекта
  • point.alpha — угол касательной к кривой в данной точке

Анимация нескольких объектов по одному пути

Можно одновременно перемещать несколько объектов по одному пути, задавая разное смещение или скорость:

var circle2 = s.circle(0, 0, 15).attr({fill: "#00f"});

Snap.animate(0, length, function(step) {
    var point1 = path.getPointAtLength(step);
    circle.attr({cx: point1.x, cy: point1.y});

    var point2 = path.getPointAtLength((step + 50) % length);
    circle2.attr({cx: point2.x, cy: point2.y});
}, 3000, mina.easeinout);
  • Использование остатка от деления (step + offset) % length позволяет создавать циклическое смещение
  • Разные объекты могут двигаться с одинаковой или различной скоростью

Использование атрибутов SVG для улучшения анимации

Snap.svg поддерживает прямую анимацию атрибутов SVG. Для путей это позволяет менять цвет, ширину, непрозрачность или даже саму форму кривой:

path.animate({stroke: "#00ff00", strokeWidth: 5}, 1000, mina.easeinout);

Для анимации формы пути используется плавное изменение строки d:

var path2 = "M50,150 C100,50 400,250 450,150";
path.animate({d: path2}, 2000, mina.easeinout);

Особенность: при анимации d важно, чтобы количество сегментов исходного и целевого пути совпадало, иначе Snap.svg может интерпретировать кривую некорректно.

Циклическая анимация и управление временной шкалой

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

function animateCircle() {
    Snap.animate(0, length, function(step) {
        var point = path.getPointAtLength(step);
        circle.attr({cx: point.x, cy: point.y});
    }, 2000, mina.easeinout, animateCircle);
}

animateCircle();
  • Коллбэк последнего аргумента запускает анимацию снова
  • Для более сложных сценариев движения можно комбинировать задержки setTimeout и последовательные анимации

Анимация по сложным кривым и комбинации трансформаций

Snap.svg позволяет комбинировать движение вдоль пути с масштабированием, прозрачностью и вращением одновременно:

Snap.animate(0, length, function(step) {
    var point = path.getPointAtLength(step);
    circle.attr({
        cx: point.x,
        cy: point.y,
        transform: "rotate(" + point.alpha + "," + point.x + "," + point.y + ") scale(" + (1 + 0.5 * Math.sin(step/20)) + ")",
        opacity: 0.5 + 0.5 * Math.sin(step/30)
    });
}, 4000, mina.easeinout);
  • scale() динамически изменяет размер
  • opacity плавно изменяет прозрачность
  • Комбинация трансформаций позволяет создавать сложные визуальные эффекты без использования CSS-анимаций

Заключение по методологии

Анимация путей в Snap.svg строится на трёх ключевых принципах: определение кривой, получение точек и углов на пути и плавная интерполяция свойств объекта. Использование этих инструментов позволяет создавать реалистичное движение объектов, управлять их ориентацией и визуальными свойствами в динамическом SVG-контейнере.