单击

时间:2017-10-17 20:12:17

标签: javascript jquery events svg svg.js

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

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

我已经搜索过如何阻止某个事件被触发并进入preventDefaul()stopPropagation()stopImmediatePropagation(),但这些都没有解决我的问题。

有没有办法让事件阻止另一个事件被解雇?

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

2 个答案:

答案 0 :(得分:1)

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

因此,在dragmove处理程序中,您可以定义类似的内容:

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

答案 1 :(得分:0)

这就是我解决这个问题的方法;

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;
    });
}