TL; DR:在元素点击时触发应该触发元素拖动的事件。
我正在使用svg.draggable.js,它有4个自定义事件,其中重要的事件是dragstart
和dragmove
。当用户点击元素时会触发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
答案 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;
});
}