单击时触发拖动事件
drag event is being fired on click
TL;DR: 应在元素拖动时触发的事件在元素单击时触发。
我正在使用 svg.draggable.js,它有 4 个自定义事件,这里重要的是 dragstart
和 dragmove
。 dragstart
在用户单击元素时触发,而 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;
});
}
TL;DR: 应在元素拖动时触发的事件在元素单击时触发。
我正在使用 svg.draggable.js,它有 4 个自定义事件,这里重要的是 dragstart
和 dragmove
。 dragstart
在用户单击元素时触发,而 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;
});
}