18910140161

JavaScript-如何限制interact.js中的拖动元素-堆栈溢出

顺晟科技

2022-10-19 12:36:06

81

我试图使用interact.js阻止元素重叠,但我不知道如何让n个元素能够这样做。有人有主意吗?或者其他我可以验证的方法。 尝试这个问题的解决方案,但我不明白如何获得元素列表来遍历它。在此处输入链接说明


顺晟科技:

由于您需要一个使用CSS transform属性的答案,我根据您更改的代码片段和旧答案的一部分制作了一个新答案。冲突将在转换偏移量上检测,而不是在top和left属性上检测。我希望您能得到这个答案。

你要找的是碰撞检测。当您移动或调整框的大小时,您可以检查新的尺寸/位置是否与其他框发生冲突。如果是这种情况,那么可以忽略移动/resize。

因为您的代码段包含了大量无效的HTML,所以我不得不剥离其中的大部分以使其正常工作。请花一些时间制作有效的HTML当/如果你问你的下一个问题。HTML代码中存在的一些错误:

  • 所有内容都在元素中生成
  • HTML标记的用法。只有特定的标签可以存在于一个标签中,如is有效,但is无效,编写一些HTML标签(如input)的正确方式是(没有结束标签)
  • 没有任何开始标记的结束标记
  • 在关闭所有子标记之前先关闭父标记
window.dragMoveListener = dragMoveListener;

    interact('.signer-box')
        .draggable({
            onmove: dragMoveListener,
            inertia: true,
            autoScroll: true,
            restrict: {
                elementRect: {top: 0, left: 0, bottom: 1, right: 1}
            }
        })
        .resizable({
            onmove: resizeMoveListener,
            inertia: true,
            edges: {left: true, right: true, bottom: true, top: true}
        })

const boxes = document.getElementsByClassName("signer-box");

function dragMoveListener(event) {
    
    const self = {
    x: event.target.offsetLeft + event.dx,
    y: event.target.offsetTop + event.dy,
    width: event.target.offsetWidth,
    height: event.target.offsetHeight
  }

  if (!collides(self, event)) {
    event.target.style.left = event.target.offsetLeft + event.dx + "px";
    event.target.style.top = event.target.offsetTop + event.dy + "px";
    var target = event.target;
    var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
    var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
    target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
    target.setAttribute('data-x', x);
    target.setAttribute('data-y', y);
    
    computeSignerBoxPosition();
  }
   
}

function resizeMoveListener(event) {
    
     const self = {
    x: event.target.offsetLeft + event.deltaRect.left,
    y: event.target.offsetTop + event.deltaRect.top,
    width: event.target.offsetWidth + event.deltaRect.width,
    height: event.target.offsetHeight + event.deltaRect.height
  }

  if (!collides(self, event)) {
    var target = event.target;
    var x = (parseFloat(target.getAttribute('data-x')) || 0);
    var y = (parseFloat(target.getAttribute('data-y')) || 0);
    x += event.deltaRect.left;
    y += event.deltaRect.top;

    target.style.width = event.rect.width + 'px';
    target.style.height = event.rect.height + 'px';
    target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px,' + y + 'px)';
    target.setAttribute('data-x', x);
    target.setAttribute('data-y', y);
    
    computeSignerBoxPosition();
  }
 }   
    
    function collides(self, event) {
  for (const box of boxes) {
    if (box == event.target) {
      continue;
    }

    const other = {
      x: box.offsetLeft,
      y: box.offsetTop,
      width: box.offsetWidth,
      height: box.offsetHeight
    }

    const collisionX = Math.max(self.x + self.width, other.x + other.width) - Math.min(self.x, other.x) < self.width + other.width;
    const collisionY = Math.max(self.y + self.height, other.y + other.height) - Math.min(self.y, other.y) < self.height + other.height;

    if (collisionX && collisionY) {
      return true;
    }
  }
  return false;
   
}

function computeSignerBoxPosition() {
    var $signatureBox = $('.signer-box');
    var sbDataX = parseFloat($signatureBox.attr('data-x'));
    var sbDataY = parseFloat($signatureBox.attr('data-y'));
    var sbOuterWidth = $signatureBox.outerWidth();
    var sbOuterHeight = $signatureBox.outerHeight();

    var w = $('#pdf-page').width();
    var h = $('#pdf-page').height();
    
    var top = sbDataX / w;
    var left = sbDataY / h;
    var width = sbOuterWidth / w;
    var height = sbOuterHeight / h;

    document.getElementById("widthValue").value = width;
    document.getElementById("heightValue").value = height;
    document.getElementById("coorX").value = top;
    document.getElementById("coorY").value = left;
}

下面是我想出的解决办法:

注意碰撞检测是用所谓的AABB碰撞检测算法完成的。它可能不是最有效的碰撞检测算法,但它是最简单的实现之一。因为你只有2个盒子,这个算法就足够了。如果您需要更多的方框,则该算法将呈指数级变慢,您可能需要投入时间研究更好的算法,例如四叉树。

  • TAG:
相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航