I'm building an application in which I'm hoping to use SVG and interact.js together for drag and drop of SVG elements. My SVG is using a ViewBox in order to scale the graphics correctly on different resolutions, but the issue is that when I drag, the mouse moves "faster" than the element its moving.
I understand that is is an issue between the coordinate system of the screen and the SVG, and I've found what appears to be an answer here: Interact JS, Drag svg elements inside viewboxed svg?
However, I can't figure out how to tie the marked answer at that link above into my code. Every different thing I try results in even more bizarre behavior. I'm trying to integrate it into the drag and drop example provided on the interact.js site:
interact('.draggable')
.draggable({
// enable inertial throwing
inertia: true,
// keep the element within the area of it's parent
restrict: {
restriction: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
// enable autoScroll
autoScroll: true,
// call this function on every dragmove event
onmove: dragMoveListener,
// call this function on every dragend event
onend: function (event) {
//removed this code for my test
}
});
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
The closest I've managed to get is with this code in place of the dragMoveListener
above:
function dragMoveListener(event) {
var target = event.target;
var svg = document.querySelector('svg');
var svgRect = svg.getBoundingClientRect();
var ctm = target.getScreenCTM();
var point = svg.createSVGPoint();
var point2;
point.x = event.clientX;
point.y = event.clientY;
point2 = point.matrixTransform(ctm);
var x = point2.x;
var y = point2.y;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
But this causes the element to be very far from the mouse, though it moves almost in sync (seems to be a bit off still). How can I get this to work, and what am I possibly misunderstanding about the solution presented at the linked question based on my "almost" solution above?
Here is the relevant HTML. All of the settings are just for testing purposes and may not be final (e.g. 2000 and 4000 are likely larger than I will ultimately need).
<svg id="svgArea" style="width:100%; border: 1px solid black" viewBox="0 0 2000 4000">
<rect id="item" width="100" height="200" stroke="#000000" stroke-width="5" fill="#ff0000" class="draggable" ></rect>
</svg>