javascript - 单击时会触发拖动事件

标签 javascript jquery events svg svg.js

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

我正在使用 svg.draggable.js,它有 4 个自定义事件,其中重要的是 dragstartdragmovedragstart 在用户单击元素时触发,而 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

最佳答案

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

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

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

关于javascript - 单击时会触发拖动事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46798428/

相关文章:

javascript - SoundCloud SDK 播放函数 - trackId 未定义

javascript - 简约的滚动 spy 将事件类仅更改为标签

Javascript 在数组中搜索

了解用户何时更改表单上的内容的 Javascript 事件

javascript - .each() 返回的问题(对象数 x 值)

javascript - 事件监听器无需点击即可运行

c# - 控制 MouseLeave 事件的问题

javascript - 计算输入字段中的字符数,然后提交

jquery - 如何使这个 jQuery 片段更加紧凑?

c# - 你如何在 C# 中引发事件?