Для работы с масштабированием (zoom) и
панорамированием (pan) в Snap.svg первым делом
необходимо создать холст. Создание холста выполняется через конструктор
Snap():
var s = Snap("#svgCanvas"); // svgCanvas — id элемента <svg>
После этого можно использовать группы
(<g>) для объединения элементов, к которым
будет применяться трансформация. Основная идея: трансформации (масштаб,
смещение) удобно применять к группе, а не к каждому элементу по
отдельности.
var group = s.group();
var rect = s.rect(0, 0, 100, 100).attr({ fill: "#3498db" });
group.add(rect);
Snap.svg использует метод transform() для применения
любых преобразований. Для масштабирования используется оператор
s (scale). Синтаксис:
element.transform("s<масштаб>[,<cx>,<cy>]");
<масштаб> — коэффициент масштабирования (1 —
исходный размер, 2 — удвоение и т.д.)<cx>, <cy> — точка центра масштабирования
(опционально, по умолчанию (0,0))Пример масштабирования группы до 150% относительно центра
(50,50):
group.transform("s1.5,50,50");
Для динамического управления масштабом удобно использовать текущую трансформацию, чтобы не сбрасывать предыдущие изменения:
var currentTransform = group.transform().localMatrix;
group.transform(currentTransform.scale(1.2, 1.2));
Здесь localMatrix возвращает матрицу текущих
трансформаций, и через нее можно последовательно применять
масштабирование и смещение, сохраняя предыдущие состояния.
Для перемещения элементов или групп применяется трансформация
t (translate):
element.transform("t<dx>,<dy>");
<dx> — смещение по оси X<dy> — смещение по оси YПример сдвига группы на 100px вправо и 50px вниз:
group.transform("t100,50");
Аналогично масштабированию, для последовательного изменения положения следует использовать текущую матрицу трансформации:
var matrix = group.transform().localMatrix;
group.transform(matrix.translate(20, 10));
Snap.svg позволяет объединять масштабирование и перемещение в одной строке трансформации:
group.transform("s1.5,50,50 t100,50");
Порядок операций важен: сначала применяется масштаб, затем сдвиг. Если порядок изменить, визуальный результат будет другим.
Для реализации интерактивного zoom & pan обычно используют
события мыши: mousedown, mousemove,
mouseup, wheel. Основная схема:
mousedown сохраняется начальная позиция курсора и
текущая матрица трансформации.mousemove рассчитывается смещение и применяется
translate.wheel рассчитывается коэффициент масштабирования и
применяется scale относительно позиции курсора.Пример обработчика масштабирования колесом мыши:
s.node.addEventListener('wheel', function(e) {
e.preventDefault();
var scale = e.deltaY < 0 ? 1.1 : 0.9;
var pt = s.node.createSVGPoint();
pt.x = e.clientX;
pt.y = e.clientY;
var svgP = pt.matrixTransform(s.node.getScreenCTM().inverse());
var matrix = group.transform().localMatrix;
matrix.translate(-svgP.x, -svgP.y).scale(scale).translate(svgP.x, svgP.y);
group.transform(matrix);
});
Эта техника позволяет масштабировать относительно позиции курсора, что создаёт естественный эффект “лупы”.
Для удобства пользователя часто применяют ограничения:
var minScale = 0.5;
var maxScale = 3;
var matrix = group.transform().localMatrix;
var newScale = Math.min(maxScale, Math.max(minScale, matrix.a * scaleFactor));
matrix.a = newScale;
matrix.d = newScale; // одинаковый масштаб по X и Y
group.transform(matrix);
Для панорамирования можно ограничить смещение, проверяя координаты:
var maxX = 500, maxY = 400;
matrix.e = Math.min(maxX, Math.max(-maxX, matrix.e));
matrix.f = Math.min(maxY, Math.max(-maxY, matrix.f));
Snap.svg поддерживает плавные анимации через метод
animate. Можно анимировать матрицу трансформации:
group.animate({ transform: "s2 t100,50" }, 500, mina.easeinout);
Для более сложных анимаций удобнее использовать матричный подход:
var matrix = new Snap.Matrix();
matrix.scale(2, 2, 50, 50);
matrix.translate(100, 50);
group.animate({ transform: matrix }, 700, mina.elastic);
Такой способ позволяет точно контролировать каждую составляющую трансформации и комбинировать эффекты.
Для масштабируемого и панорамного интерфейса рекомендуется:
group.mousedown/mousemove.Эта структура подходит как для статических графиков, так и для интерактивных схем, карт или визуализаций с динамическим изменением размеров и позиции элементов.