【问题标题】:Resizing with snap in interact.js在 interact.js 中使用 snap 调整大小
【发布时间】:2020-04-03 22:06:57
【问题描述】:

在这个jsFiddle 中,我有一个interact.js 矩形,可以通过10 像素×10 像素的快照调整其大小。矩形位于 x = 95px 中,当我将左侧移动到左侧时,它会移动到 x = 90x。这很好,但是右侧也向右移动,它不应该。

这段代码有什么问题?矩形有句柄,这是造成问题吗?

  .on('resizemove', function(event) {

    const target = event.target.querySelector('rect');

    for (const attr of ['width', 'height']) {
      let v = Number(target.getAttribute(attr));
      v += event.deltaRect[attr];
      target.setAttribute(attr, Math.round(v/10)*10);
    }

    for (const attr of ['top', 'left']) {
      const a = attr == 'left' ? 'x' : 'y';
      let v = Number(target.getAttribute(a));
      v += event.deltaRect[attr];
      target.setAttribute(a, Math.round(v/10)*10);
    }

    findLocations(rect, handles);


 });

【问题讨论】:

  • 您是说您希望未与之交互的一侧对齐网格吗?
  • 没错,如果你不明确移动那一侧,它就不应该移动
  • 这个矩形会被移动,还是只是调整大小
  • 本例中只调整大小(实际情况下也是拖动)

标签: javascript interact.js


【解决方案1】:

啊,我看到了问题。这是发生的事情:当调整矩形的大小时,您将四舍五入大小和位置。这具有以下效果:

  • 你有一个矩形,它的边从x = 95x = 115。它的左侧移动了-3 个单位。现在是92115
  • 您检查宽度:宽度是115 - 92 = 23 单位,因此您四舍五入到最接近的十位:20 单位。
  • 您检查位置:它位于92,因此您将其移动到90这会将已调整大小的整个矩形滑过。

您需要以不同于rightbottom 情况的方式处理topleft 情况,因为前两种情况会在其大小之上更新矩形位置。最重要的是,您只需要对已更改的相应边进行舍入:您不想在向右移动时将底部舍入。

  • 对于lefttop...
    • xy 移动到新位置,四舍五入
    • 不要围绕widthheight,因为这会移动rightbottom
  • 对于rightbottom...
    • 不要对xy 执行任何操作,因为对它们进行四舍五入会使整个矩形超出
    • 好吧,我们仍然可以更改 xy,因为它们将为零,但我们无法舍入它们!
    • 更改widthhight,但这次要四舍五入

要检查的情况很多,但是通过使用函数,这并不难看出它是如何工作的:

.on('resizemove', function(event) {
  const target = event.target.querySelector('rect');

  function changeVal(attr, change, round) {
    let val = Number(target.getAttribute(change));
    val += event.deltaRect[attr];
    if (round) val = Math.round(val / 10) * 10;
    target.setAttribute(change, val);
  }

  let round = false;
  if (event.deltaRect.top != 0) round = true;
  changeVal('top', 'y', round);

  round = false;
  if (event.deltaRect.left != 0) round = true;
  changeVal('left', 'x', round);

  round = false;
  if (event.deltaRect.right != 0) round = true;
  changeVal('width', 'width', round);

  round = false;
  if (event.deltaRect.bottom != 0) round = true;
  changeVal('height', 'height', round);

  findLocations(rect, handles);
});

缩短它并更改为与以前相同的循环样式:

.on('resizemove', function(event) {
  const target = event.target.querySelector('rect');

  const attributes = [
    { check: 'top', change: 'y' },
    { check: 'left', change: 'x' },
    { check: 'right', change: 'width' },
    { check: 'bottom', change: 'height' }
  ];

  for (const {check, change} of attributes) {
    let val = Number(target.getAttribute(change));
    val += event.deltaRect[check];
    if (event.deltaRect[check]) val = Math.round(val / 10) * 10;
    target.setAttribute(change, val);
  }

  findLocations(rect, handles);
});

这使用了ES6 destructuring assignment,所以它在IE中不起作用。


调整左边缘的大小时,右边缘似乎仍然有些卡顿,但我认为这是舍入错误...?

即使没有,我希望这足以让你开始。

【讨论】:

  • 是的,正确的移动可能是因为四舍五入,我认为四舍五入不起作用,我试图为this寻找解决方案
  • @ps0604 如果您还没有尝试,我会尝试的最后一件事是在'resizemove' 事件处理程序中设置一个断点并观察它调整大小时会发生什么:看看您是否能理解为什么正确边缘在移动?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 2021-09-20
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多