Моя рекомендация: не беспокойтесь о свойствах movementX
/ Y
в событии.Просто позаботьтесь о том, где мышь появилась и где она находится сейчас.
(Это дает дополнительное преимущество, заключающееся в том, что вы получаете тот же результат, даже если пропустите некоторые события: возможно, из-за того, что мышь вышла из окна, или, может быть,потому что вы хотите сгруппировать события, чтобы вы запускали код только один раз для каждого кадра анимации.)
Для места, где была запущена мышь, вы измеряете это по событию mousedown.Преобразуйте его в позицию в координатах SVG, используя метод, который вы использовали, с .getScreenCTM().inverse()
и .matrixTransform()
.После этого преобразования вам все равно, где на экране находится этот пункт.Вы заботитесь только о том, где это на картинке.Это точка на рисунке, которую вы всегда будете перемещать, чтобы находиться под мышью.
В событиях mousemove вы используете тот же метод преобразования, чтобы узнать, где в данный момент находится мышь в пределах текущей координаты SVG.система.Затем вы выясните, как далеко это находится от точки (опять же, в координатах SVG), которую вы хотите под мышью.Это сумма, которую вы используете для преобразования графики.Я последовал вашему примеру и выполняю преобразование, сдвигая x
и y
части viewBox
:
function move(e) {
var targetPoint = svgCoords(event, svg);
shiftViewBox(anchorPoint.x - targetPoint.x,
anchorPoint.y - targetPoint.y);
}
Вы также можете переместить изображение с помощью transform
нагруппа (<g>
элемент) в SVG;просто используйте тот же самый групповой элемент для вызова getScreenCTM()
, который конвертируется из координат события clientX
/ Y
.
Полная демонстрация для перетаскивания на панорамирование.Я пропустил весь ваш код рисования и эффект масштабирования.Но масштаб все равно должен работать, потому что единственная позиция, которую вы сохраняете в глобальных значениях, уже преобразована в координаты SVG.
var svg = document.querySelector("svg");
var anchorPoint;
function shiftViewBox(deltaX, deltaY) {
svg.viewBox.baseVal.x += deltaX;
svg.viewBox.baseVal.y += deltaY;
}
function svgCoords(event,elem) {
var ctm = elem.getScreenCTM();
var pt = svg.createSVGPoint();
// Note: rest of method could work with another element,
// if you don't want to listen to drags on the entire svg.
// But createSVGPoint only exists on <svg> elements.
pt.x = event.clientX;
pt.y = event.clientY;
return pt.matrixTransform(ctm.inverse());
}
svg.addEventListener("mousedown", function(e) {
anchorPoint = svgCoords(event, svg);
window.addEventListener("mousemove", move);
window.addEventListener("mouseup", cancelMove);
});
function cancelMove(e) {
window.removeEventListener("mousemove", move);
window.removeEventListener("mouseup", cancelMove);
anchorPoint = undefined;
}
function move(e) {
var targetPoint = svgCoords(event, svg);
shiftViewBox(anchorPoint.x - targetPoint.x,
anchorPoint.y - targetPoint.y);
}
body {
display: grid;
margin: 0;
min-height: 100vh;
}
svg {
margin: auto;
width: 70vmin;
height: 70vmin;
border: thin solid gray;
cursor: move;
}
<svg viewBox="-40 -40 80 80">
<polygon fill="skyBlue"
points="0 -40, 40 0, 0 40 -40 0" />
</svg>