In this jsFiddle I have an SVG
interact.js
rect that when resized it snaps to a grid.
This works fine until I start changing margins from zero to a number. The rect is inside a div #mysvg
and if I change the margins of the div, the rect snaps incorrectly (there's a shift).
Try changing in the CSS the margins from:
#mysvg {
margin-top: 0px;
margin-left: 0px;
}
To:
#mysvg {
margin-top: 12px;
margin-left: 12px;
}
Then rerun the jsFiddle and you'll see the problem.
Similar issue happens when the body margin is incremented from zero.
How to fix this problem? Is there a way to make the interact.js
resize relative to the div, ignoring its margin or where the div is positioned on the page (for example, the div may be located inside another div)?
There is an offset
property in interact.snappers.grid
which you can use to offset the grid snap:
modifiers: [
interact.modifiers.snap({
targets: [
interact.snappers.grid({
x: 20,
y: 20,
// Here set the offset x, y
// to the margins top and left of the SVG
offset: { x: 12, y: 12 }
}),
]
})
]
You can check it working with #mysvg
margin-top
and margin-left
set to 12px
in this jsFiddle, or run the below code snippet:
var svg = document.getElementById('mysvg');
// draw vertical lines
var gridSize = 20;
for (var i=0;i < 100;i++){
var line = document.createElementNS("http://www.w3.org/2000/svg", "line");
svg.appendChild(line);
line.setAttribute("x1", (i + 1) * gridSize)
line.setAttribute("y1", 0)
line.setAttribute("x2", (i + 1) * gridSize)
line.setAttribute("y2", 500)
line.setAttribute("stroke-width", 1)
line.setAttribute("stroke", 'gray');
}
// draw vertical lines
for (var i=0;i < 100;i++){
var line = document.createElementNS("http://www.w3.org/2000/svg", "line");
svg.appendChild(line);
line.setAttribute("x1", 0)
line.setAttribute("y1", (i + 1) * gridSize)
line.setAttribute("x2", 2000)
line.setAttribute("y2", (i + 1) * gridSize)
line.setAttribute("stroke-width", 1)
line.setAttribute("stroke", 'gray');
}
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
svg.appendChild(rect);
rect.setAttribute('x', 90);
rect.setAttribute('y', 90);
rect.setAttribute('width', 100);
rect.setAttribute('height', 100);
rect.setAttribute('class', 'resize-me');
rect.setAttribute('stroke-width', 2);
rect.setAttribute('stroke', 'black');
rect.setAttribute('fill', 'orange');
interact('.resize-me')
.resizable({
edges: { left: true, right: true, bottom: true, top: true },
margin: 3,
modifiers: [
interact.modifiers.snap({
targets: [
interact.snappers.grid({
x: 20,
y: 20,
// Here set the offset x, y
// to the margins top and left of the SVG
offset: { x: 12, y: 12 }
}),
]
})
]
})
.on('resizemove', function(event) {
var target = event.target;
var x = (parseFloat(target.getAttribute('endx')) || 0)
var y = (parseFloat(target.getAttribute('endy')) || 0)
target.setAttribute('width', event.rect.width);
target.setAttribute('height', event.rect.height);
x += event.deltaRect.left
y += event.deltaRect.top
target.setAttribute('transform', 'translate(' + x + ', ' + y + ')')
target.setAttribute('endx', x)
target.setAttribute('endy', y)
});
svg {
width: 100%;
height: 240px;
-ms-touch-action: none;
touch-action: none;
box-sizing: border-box;
}
body { margin: 0px }
#mysvg {
margin-top: 12px;
margin-left: 12px;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs@latest/dist/interact.min.js"></script>
<svg id="mysvg"></svg>