interact.js SVG 矩形对齐 div 有边距

interact.js SVG rect snapping to a div with margins

在这个 jsFiddle 中,我有一个 SVG interact.js 矩形,当调整大小时它会捕捉到网格。

在我开始将页边距从零更改为数字之前,它工作正常。矩形位于 div #mysvg 内,如果我更改 div 的边距,则矩形会错误地对齐(有偏移)。

尝试更改 CSS 的页边距:

#mysvg { 
   margin-top: 0px; 
   margin-left: 0px; 
}

收件人:

#mysvg { 
   margin-top: 12px; 
   margin-left: 12px; 
}

然后重新运行 jsFiddle,您就会看到问题。

当正文边距从零开始递增时,会发生类似的问题。

如何解决这个问题?有没有办法使 interact.js 相对于 div 调整大小,忽略其边距或 div 在页面上的位置(例如,div 可能是位于另一个 div) 内?

有一个 offset property in interact.snappers.grid 可以用来偏移网格捕捉:

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 }

      }),
    ]
  })
]

您可以在 #mysvg margin-topmargin-left 设置为 12pxjsFiddle 或下面的 运行 的情况下检查它是否正常工作代码片段:

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>