简体   繁体   中英

drag event is being fired on click

TL;DR: event that should be fired on element drag is being fired on element click.

I'm using svg.draggable.js and it has 4 custom events, the ones important here are dragstart and dragmove . dragstart fires when the user clicks the element, while dragmove fires on every update on the element position. The problem is that dragmove is fired when the element is clicked too, therefore running logic that it should not (well, at least in my case).

I've already searched on how to stop an event from firing and got to preventDefaul() , stopPropagation() and stopImmediatePropagation() but none of these solves my problem.

Is there a way to make an event prevent another event from firing?

PS: there's an open issue on the repository, but I'm trying to find an "agnostic" way to do this.

Code:

What should happen on click:

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

What should happen while dragging the element:

 // while dragging DragHandler.prototype.drag = function(e){ var box = this.getBBox(), p = this.transformPoint(e), x = this.startPoints.box.x + (px - this.startPoints.point.x) + this.startPoints.offset, y = this.startPoints.box.y + (py - 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); } }; 

There's a bit of own code on these snippets but in general it is from svg.draggable.js

One way I imagine to get around that is to define a flag that is set to true when dragstart is invoked, then inside dragmove handler you clear that flag the first time (so the logic is not invoked when the element is clicked).

So inside the dragmove handler you define something like:

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

This is how I've solved this problem;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM