
dgrm.net | GitHub
Как сделан zoom в редакторе блок-схем dgrm.net.
Zoom-ить можно:
колесиком мышки,
touchpad-ом
и двумя пальцами на телефонах и планшетах.
Готовая функция zoom-а SVG для ваших проектов прилагается. Для HTML можно переделать.
Алгоритм zoom-а
В SVG и HTML есть масштабирование. Масштабирование в HTML.
Только менять масштаб не достаточно. Изображение будет уезжать.
При увеличении круг в центре экрана съезжает вниз вправо.


Черный прямоугольник это экран. Синий это увеличенное изображение. Увеличенный круг находится в центре увеличенного изображения, но съехал относительно экрана.
Нужно увеличивать и сдвигать, тогда центр изображения не уедет.

На рисунке 4 центр изображения не съезжает. Но карты работают не так. Карты зумятся не в центр. Карты зумятся относительно курсора. Место, куда указывает курсор, не сдвигается относительно экрана.
Здание в центре карты уезжает вниз. Оно выделено красным. Здание под курсором остается на месте. Выделено синим.

Значит функция зума должна сдвигать изображение так, чтобы точка под курсором оставалась на месте.
/**
* @param {SVGGraphicsElement} svgEl
* @param {Point} fixedPoint this point will not change position while scale
* @param {number} scale
* @param {number} nextScale
*/
export function svgScale(svgEl, fixedPoint, scale, nextScale) {
const position = svgPositionGet(svgEl);
svgPositionSet(svgEl, {
x: nextScale / scale * (position.x - fixedPoint.x) + fixedPoint.x,
y: nextScale / scale * (position.y - fixedPoint.y) + fixedPoint.y
});
ensureTransform(svgEl, SVGTransform.SVG_TRANSFORM_SCALE)
.setScale(nextScale, nextScale);
}Листинг 1. Функция зума. Сдвигает изображение так, что fixedPoint остается на месте.
Вспомогательные функции svgPositionGet, svgPositionSet, ensureTransform смотрите на GitHub.
Zoom колесиком мышки и touchpad-ом
Подписываемся на событие колесика мышки “wheel”. Для щипка двумя пальцами на touchpad отдельного события нет. Щипок использует это же событие “wheel”.
Для колесика масштаб изменяется с шагом 0.25, а для touchpad 0.05. Значения подобраны так чтобы:
колесико мышки не нужно было долго крутить,
а на touchpad изображение не скакало.
// 'svg' is type of {SVGSVGElement}
// mouse wheel, trackpad pitch
svg.addEventListener('wheel', /** @param {WheelEvent} evt */ evt => {
evt.preventDefault();
// calc nextScale
const delta = evt.deltaY || evt.deltaX;
const scaleStep = Math.abs(delta) < 50
? 0.05 // touchpad pitch
: 0.25; // mouse wheel
const scaleDelta = delta < 0 ? scaleStep : -scaleStep;
const nextScale = scale + scaleDelta; // 'scale' is previous scale
// calc fixedPoint
const fixedPoint = { x: evt.clientX, y: evt.clientY };
// scale
// 'svgEl' is element to scale
svgScale(svgEl, fixedPoint, scale, nextScale);
});Листинг 2. Подписываемся на событие колесика мышки. Щипок touchpad запускает это же событие. Полный код смотрите на GitHub.
Zoom двумя пальцам на телефонах и планшетах
Для zoom-а пальцами фиксированная точка - это точка посередине между пальцами. Изменение масштаба зависит от изменения расстояния между пальцами.
Еще нужно учитывать что изображение можно одновременно зумить и двигать.
// calc nextScale
// distance between fingers
const distanceNew = Math.hypot(
firstFinger.x - secondFinger.x,
firstFinger.y - secondFinger.y);
// 'distance' variable is previous distance between fingers
const scaleDelta = (distanceNew - distance) * 0.01;
const nextScale = scale + scaleDelta; // 'scale' is previous scale
// calc fixedPoint
const fixedPoint = {
x: (firstFinger.x + secondFinger.x) / 2,
y: (firstFinger.y + secondFinger.y) / 2
};
// scale
// 'svgEl' is element to scale
svgScale(svgEl, fixedPoint, scale, nextScale);
// don't forget to also move the canvas behind your fingersЛистинг 3. При zoom-е пальцами фиксированная точка это точка посередине между пальцами. Изменение масштаба зависит от изменения расстояния между пальцами. Полный код смотрите на GitHub.
Другие статьи про dgrm.net
JavaScript редактор SVG диаграмм который весит в 6,5 раз меньше bootstrap (библиотека с открытым исходным кодом)
JavaScript редактор диаграмм, который открывает диаграммы из PNG картинок (open source)
JavaScript редактор текста для SVG
UI редактора блок-схем
Как поддержать проект
Начните использовать, расскажите что думаете.
Любым способом: комментарии, личные сообщения, на GitHub.
Все читаю, веду список предложений.Расскажите знакомым.
Ставьте звездочки на GitHub.
