单击时触发拖动事件

drag event is being fired on click

TL;DR: 应在元素拖动时触发的事件在元素单击时触发。

我正在使用 svg.draggable.js,它有 4 个自定义事件,这里重要的是 dragstartdragmovedragstart 在用户单击元素时触发,而 dragmove 在元素位置的每次更新时触发。问题是当元素也被点击时 dragmove 被触发,因此 运行 逻辑它不应该(好吧,至少在我的情况下)。

我已经搜索了如何阻止事件触发并找到了 preventDefaul()stopPropagation()stopImmediatePropagation(),但是其中的 none 解决了我的问题。

有没有办法让一个事件阻止另一个事件触发?

P.S:存储库中有一个 open issue,但我正试图找到一种“不可知论”的方法来做到这一点。

代码:

点击时会发生什么:

// start dragging
  DragHandler.prototype.start = function(e){
    // check for left button
    if(e.type == 'click'|| e.type == 'mousedown' || e.type == 'mousemove'){
      if((e.ctrlKey || e.metaKey)/*if Ctrl or cmd key pressed, then Multi Select*/ || (e.which || e.buttons) != 1){
          return;
      }
    }

    var _this = this;

    // fire beforedrag event
    this.el.fire('beforedrag', { event: e, handler: this });

    // search for parent on the fly to make sure we can call
    // draggable() even when element is not in the dom currently
    this.parent = this.parent || this.el.parent(SVG.Nested) || this.el.parent(SVG.Doc);
    this.p = this.parent.node.createSVGPoint();

    // save current transformation matrix
    this.m = this.el.node.getScreenCTM().inverse();

    var box = this.getBBox();

    var anchorOffset = 0;
    var anchorOffsetVertical = 0;

    // fix text-anchor in text-element (#37)
    if(this.el instanceof SVG.Text) {
      var tChildren = this.el.node.children;

      if (tChildren && tChildren.length) {
        for(var i = 0; i < tChildren.length; i++) {
          var currentOffset = tChildren[i].getComputedTextLength();

          if (currentOffset > anchorOffset) {
            anchorOffset = currentOffset;
          }
        }
      } else {
        anchorOffset = this.el.node.getComputedTextLength();
      }

      switch(this.el.node.style.textAnchor || this.el.attr('text-anchor')){
        case 'middle':
          anchorOffset /= 2;
          break;
        case 'start':
          anchorOffset = 0;
          break;
      }
    }

    this.startPoints = {
      // We take absolute coordinates since we are just using a delta here
      point: this.transformPoint(e),
      box: box,
      offset: anchorOffset
    };

    // add drag and end events to window
    SVG.on(window, 'mousemove.drag', function(e){ _this.drag(e); });
    SVG.on(window, 'touchmove.drag', function(e){ _this.drag(e); });
    SVG.on(window, 'mouseup.drag', function(e){ _this.end(e); });
    SVG.on(window, 'touchend.drag', function(e){ _this.end(e); });

    // fire dragstart event
    this.el.fire('dragstart', {event: e, p: this.p, m: this.m, handler: this});

    // prevent browser drag behavior
    e.preventDefault();
  };

拖动元素时会发生什么:

// while dragging
  DragHandler.prototype.drag = function(e){
    var box = this.getBBox(),
        p   = this.transformPoint(e),
        x   = this.startPoints.box.x + (p.x - this.startPoints.point.x) + this.startPoints.offset,
        y   = this.startPoints.box.y + (p.y - this.startPoints.point.y),
        c   = this.constraint,
        s   = this.el.transform().matrix.a;

    this.el.fire('dragmove', { event: e, p: this.p, m: this.m, handler: this });

    // move the element to its new position, if possible by constraint
    if (typeof c == 'function') {
      var coord = c.call(this.el, x, y, this.m);

      if (typeof coord == 'boolean') {
        coord = {
          x: coord,
          y: coord
        };
      }

      // if true, we just move. If !false its a number and we move it there
      if (coord.x === true) {
        this.el.x(x);
      } else if (coord.x !== false) {
        this.el.x(coord.x);
      }

      if (coord.y === true) {
        this.el.y(y);
      } else if (coord.y !== false) {
        this.el.y(coord.y);
      }
    } else if (typeof c == 'object') {
      // keep element within constrained box
      if (c.minX !== null && x < c.minX)
        x = c.minX;
      else if (c.maxX !== null && x > c.maxX - box.width){
        x = c.maxX - box.width;
      }if (c.minY !== null && y < c.minY)
        y = c.minY;
      else if (c.maxY !== null && y > c.maxY - box.height)
        y = c.maxY - box.height;

      this.el.move(x, y);
      // console.log(x, y, s);
    }
  };

这些片段中有一些自己的代码,但通常来自 svg.draggable.js

我想解决这个问题的一种方法是定义一个标志,该标志在调用 dragstart 时设置为 true,然后在 dragmove 处理程序中您第一次清除该标志(因此单击元素时不会调用逻辑)。

因此,在 dragmove 处理程序中,您定义如下内容:

if(flag) {
  flag = false;
  return
}
else {
  // your logic for dragmove here
}

我就是这样解决这个问题的;

function onMouse(shape, dragCB, clickCB){
    var mousestate = 0;
    shape.on( 'mousedown', function() {
        mousestate = 1;
    });
    shape.on( 'mousemove', function() {
        if(mousestate === 1) mousestate = 2;
    });
    shape.on( 'mouseup', function(e) {
        if(mousestate === 2) {
            dragCB(e);
        }else{
            clickCB(e) 
        }
        mousestate = 0;
    });
}