Snap.svg предоставляет удобные инструменты для динамического
управления SVG-графикой, однако она не имеет встроенного механизма
автоматического реагирования на изменение размеров окна браузера. Для
реализации адаптивной графики используется комбинация Snap.svg и
стандартных возможностей Jav * aScript: события resize и
методы перерасчёта размеров и координат элементов.
window.addEventListener('resize', resizeHandler);
function resizeHandler() {
// Логика пересчета размеров SVG и элементов
}
Событие resize срабатывает каждый раз, когда изменяются
размеры окна. Внутри обработчика можно изменять размеры контейнера
<svg> или отдельных элементов.
Первый шаг — привязка размеров SVG к размерам окна:
var s = Snap("#svgCanvas");
function resizeSVG() {
var width = window.innerWidth;
var height = window.innerHeight;
s.attr({
width: width,
height: height
});
}
window.addEventListener('resize', resizeSVG);
resizeSVG(); // первичная установка размеров
Использование метода attr позволяет динамически менять
атрибуты width и height SVG-контейнера без
потери графики. Это особенно важно для интерактивных визуализаций, где
размеры элементов должны оставаться пропорциональными экрану.
Изменение размеров окна требует корректировки размеров и координат отдельных элементов, чтобы сохранить визуальную целостность:
var circle = s.circle(100, 100, 50); // исходная позиция и радиус
var originalWidth = 800;
var originalHeight = 600;
function resizeElements() {
var scaleX = window.innerWidth / originalWidth;
var scaleY = window.innerHeight / originalHeight;
circle.attr({
cx: 100 * scaleX,
cy: 100 * scaleY,
r: 50 * Math.min(scaleX, scaleY)
});
}
window.addEventListener('resize', resizeElements);
resizeElements();
В этом примере используется масштабирование по обеим осям с
сохранением пропорций радиуса через
Math.min(scaleX, scaleY). Такой подход предотвращает
искажение кругов и квадратов.
Snap.svg поддерживает <g>-элементы и методы
трансформации (transform). Это позволяет масштабировать
целые группы объектов относительно определённой точки:
var group = s.group(
s.rect(50, 50, 100, 100),
s.circle(150, 150, 50)
);
function scaleGroup() {
var scaleX = window.innerWidth / originalWidth;
var scaleY = window.innerHeight / originalHeight;
group.transform(`scale(${scaleX}, ${scaleY})`);
}
window.addEventListener('resize', scaleGroup);
scaleGroup();
Использование transform с scale экономит
вычисления координат каждого объекта, позволяя изменять размеры группы
целиком.
Событие resize может срабатывать очень часто, что
приводит к значительной нагрузке при сложной графике. Для оптимизации
используется техника дебаунсинга:
let resizeTimeout;
window.addEventListener('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
resizeSVG();
resizeElements();
scaleGroup();
}, 100);
});
Дебаунсинг гарантирует, что функции перерасчёта будут вызваны не чаще одного раза за указанный интервал, снижая нагрузку на браузер.
При динамическом изменении окна важно учитывать, что соотношение ширины и высоты может меняться. Для сохранения макета используют нормированные координаты:
function normalize(value, maxValue) {
return value / maxValue;
}
function resizeNormalized() {
var width = window.innerWidth;
var height = window.innerHeight;
circle.attr({
cx: normalize(100, originalWidth) * width,
cy: normalize(100, originalHeight) * height,
r: normalize(50, originalWidth) * width
});
}
window.addEventListener('resize', resizeNormalized);
resizeNormalized();
Такой подход позволяет адаптировать любые фигуры, даже если размеры контейнера меняются не пропорционально.
Snap.svg поддерживает атрибут viewBox, который
обеспечивает автоматическое масштабирование содержимого:
s.attr({
viewBox: `0 0 ${originalWidth} ${originalHeight}`,
preserveAspectRatio: "xMidYMid meet",
width: window.innerWidth,
height: window.innerHeight
});
viewBox задаёт виртуальные координаты, а
preserveAspectRatio контролирует сохранение пропорций. Это
избавляет от необходимости вручную пересчитывать координаты большинства
элементов, особенно при сложных композициях.
Для проектов с большим количеством элементов рекомендуется комбинировать методы:
viewBox для глобального
масштабирования.transform при
необходимости.Такой подход обеспечивает плавную адаптацию графики, минимизирует вычислительные затраты и сохраняет визуальную целостность интерфейса при изменении размеров окна.