Raphael JS中拖动矩形来回弹跳

Dragging a rectangle in Raphael JS bounces back and forth

在这个 jsFiddle 中,我有一个带有矩形的 Raphael JS 网格,我需要将其移动到网格。矩形的每个角都有四个红色手柄,当它移动时手柄也会移动。

到目前为止,我可以四处移动矩形(效果很好),但是当我尝试将其向左移动时,矩形会闪烁并来回弹跳。问题可能是我在拖动 move 函数中设置了 x 矩形坐标吗?任何想法将不胜感激。

   var move = function(dx, dy) {
    rect.attr("x", ox + dx);
    rect.attr("y", oy + dy);
    leftTop.attr("x", ox1 + dx);
    leftTop.attr("y", oy1 + dy);
    rightTop.attr("x", ox2 + dx);
    rightTop.attr("y", oy2 + dy);
    leftBottom.attr("x", ox3 + dx);
    leftBottom.attr("y", oy3 + dy);
    rightBottom.attr("x", ox4 + dx);
    rightBottom.attr("y", oy4 + dy);

    if ((dx - lastdx) < 0)
        seeMoveLeft(rect, leftTop, rightTop,
                 leftBottom, rightBottom);

    lastdx = dx; 

};

var up = function() {};

rect.drag(move, start, up);


var seeMoveLeft = function (rect, leftTop, rightTop,
                 leftBottom, rightBottom){
    var left = rect.attr('x');
    // find next left grid
    var found = false;
    var min = left - 40;
    for (var i=left; i>=min; i--){
       if (i % 40 == 0) {
          found = true;
          break;
       }
    }

    if (found) {
        var diff = left - i;
        rect.attr('x', i);
        var lt = leftTop.attr('x');
        leftTop.attr('x', lt - diff);
        var rt = rightTop.attr('x');
        rightTop.attr('x', rt - diff);
        var lb = leftBottom.attr('x'); 
        leftBottom.attr('x', lb - diff);
        var rb = rightBottom.attr('x');
        rightBottom.attr('x', rb - diff);

    }

}

问题是你在这里设置了 rect 的新 x:

rect.attr("x", ox + dx);

那你在这里修改一下:

if ((dx - lastdx) < 0)
        seeMoveLeft(rect, leftTop, rightTop,
                 leftBottom, rightBottom);

但是由于移动函数是基于 mousemove 事件的,所以有时候,你会在一个过程中得到相同的 dx 值 2 次排。这对于 mousemove 事件是正常的,尤其是当你移动缓慢时。您可以在下面尝试,每次 clientX 保持不变时,window 将变为绿色。

var lastClientX;
window.addEventListener('mousemove', (e) => {

  if (lastClientX && e.clientX === lastClientX) {
    document.body.style.backgroundColor = 'green';
  } else {
    document.body.style.backgroundColor = 'yellow';
  }

  lastClientX = e.clientX;

})
body {
  width: 100%;
  height 100%;
}

当你有 2 个连续相同的 dx 时,你的情况会发生什么,x - lastdx 不会验证,因此位置不会调整,会保持不变在 rect.attr("x", ox + dx);。所以第一次移动事件,位置调整到seeMoveLeft的网格,然后位置改变但不调整,因为dx不小比 lastdx 相等。因此你看到了闪烁。

最简单的纠正方法,如果 dxlastdx 相同,则跳过定位。像这样:

if(lastdx !== dx){
    rect.attr("x", ox + dx);
    leftTop.attr("x", ox1 + dx);
    rightTop.attr("x", ox2 + dx);
    leftBottom.attr("x", ox3 + dx);
    rightBottom.attr("x", ox4 + dx);
  }

https://jsfiddle.net/ce7sh9ov/1/