В библиотеке Snap.svg анимация элементов SVG может быть реализована
как через встроенные методы Snap, так и с использованием нативного API
браузера — requestAnimationFrame. Этот подход обеспечивает
более плавную анимацию и экономию ресурсов, так как браузер
синхронизирует обновления с частотой перерисовки экрана.
requestAnimationFrame принимает функцию обратного
вызова, которая вызывается перед следующим перерисовыванием страницы.
Использование его с Snap.svg позволяет напрямую управлять свойствами
элементов и анимационными шагами.
var s = Snap(400, 400);
var circle = s.circle(50, 50, 40).attr({fill: "#3498db"});
function animateCircle(timestamp) {
var speed = 0.1; // пикселей за миллисекунду
circle.attr({cx: circle.attr("cx") + speed});
if (circle.attr("cx") < 400) {
requestAnimationFrame(animateCircle);
}
}
requestAnimationFrame(animateCircle);
В этом примере круг плавно перемещается по оси X. Использование
requestAnimationFrame вместо setInterval или
setTimeout гарантирует, что анимация будет максимально
синхронизирована с обновлением экрана.
Для точного контроля скорости и движения важно учитывать
временные метки, которые передаются в колбэк
requestAnimationFrame. Это позволяет вычислять смещение на
основе реального времени, а не фиксированных шагов:
var start = null;
var circle = s.circle(50, 200, 30).attr({fill: "#e74c3c"});
function animate(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
var newX = 50 + progress * 0.2; // скорость 0.2 пикселя на миллисекунду
circle.attr({cx: newX});
if (newX < 400) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
Использование разницы между текущей временной меткой и стартовой позволяет создавать анимации с постоянной скоростью независимо от задержек между кадрами.
Snap.svg предоставляет метод animate, но иногда
необходимо реализовать сложные анимации с кастомной логикой, например
движение по кривой Безье или анимацию нескольких свойств одновременно с
разными скоростями. В таких случаях удобно использовать
requestAnimationFrame:
var path = s.path("M10,80 C40,10 65,10 95,80").attr({stroke: "#2ecc71", fill: "none"});
var circle = s.circle(10, 80, 5).attr({fill: "#2ecc71"});
var start = null;
function animateAlongPath(timestamp) {
if (!start) start = timestamp;
var progress = (timestamp - start) / 2000; // 2 секунды на полное движение
if (progress > 1) progress = 1;
var point = Snap.path.getPointAtLength(path, progress * path.getTotalLength());
circle.attr({cx: point.x, cy: point.y});
if (progress < 1) {
requestAnimationFrame(animateAlongPath);
}
}
requestAnimationFrame(animateAlongPath);
Здесь Snap.path.getPointAtLength используется для
вычисления координат по длине пути. Такой подход позволяет создавать
точные и сложные траектории движения.
attr для разных свойств, лучше
передавать объект с несколькими ключами.getTotalLength() каждый кадр.var pathLength = path.getTotalLength();
function optimizedAnimate(timestamp) {
if (!start) start = timestamp;
var progress = (timestamp - start) / 2000;
if (progress > 1) progress = 1;
var point = Snap.path.getPointAtLength(path, progress * pathLength);
circle.attr({cx: point.x, cy: point.y});
if (progress < 1) requestAnimationFrame(optimizedAnimate);
}
requestAnimationFrame(optimizedAnimate);
Для синхронного движения нескольких объектов удобно использовать одну
функцию requestAnimationFrame, которая обновляет все
элементы сразу. Это снижает нагрузку на рендеринг и упрощает управление
временем:
var circle1 = s.circle(50, 50, 20).attr({fill: "#f1c40f"});
var circle2 = s.circle(50, 100, 20).attr({fill: "#9b59b6"});
var start = null;
function animateAll(timestamp) {
if (!start) start = timestamp;
var progress = (timestamp - start) / 2000;
if (progress > 1) progress = 1;
circle1.attr({cx: 50 + 200 * progress});
circle2.attr({cx: 50 + 100 * progress});
if (progress < 1) requestAnimationFrame(animateAll);
}
requestAnimationFrame(animateAll);
Такой подход обеспечивает единый тайминг и простое управление последовательностью анимаций, включая остановку и повтор.
Использование requestAnimationFrame с Snap.svg открывает
возможности для создания плавных, оптимизированных анимаций с точным
контролем времени и траекторий. Оно позволяет реализовать сложные
сценарии, которые трудно или невозможно воспроизвести только через метод
animate Snap.svg. Управление временными метками,
предварительные вычисления и групповое обновление атрибутов делают
анимации более производительными и предсказуемыми.