我正在尝试使用Canvas作为渲染器在Dojo的gfx中实现橡皮筋选择框。我的目的是在单击鼠标并拖动鼠标时绘制选择框,然后在释放鼠标后消失。不幸的是我遇到了一个问题。
jsFiddle示例:http://jsfiddle.net/7F9fy/
主要问题是在onmousemove(或与之相关)的某处:
whiteRect.connect("onmousemove",function(e) {
if(isMouseDown) {
if(whiteRect.groupSelector_) {
pStat.innerHTML = "dragging...";
console.debug("dragging...");
e.stopImmediatePropagation();
e.preventDefault();
var ex = (e.x ? e.x : e.clientX);
var ey = (e.y ? e.y : e.clientY);
if(groupSelector) {
// Also tried getShape, editing that shape, and setShape on groupSelector--same
// behavior, though.
var rectX = (ex - cnvDiv.offsetLeft < whiteRect.groupSelector_.x ? ex - cnvDiv.offsetLeft : whiteRect.groupSelector_.x);
var rectY = (ey - cnvDiv.offsetTop < whiteRect.groupSelector_.y ? ey - cnvDiv.offsetTop : whiteRect.groupSelector_.y);
surface.remove(groupSelector);
groupSelector = surface.createRect({
x: rectX,
y: rectY,
width: Math.abs(ex - cnvDiv.offsetLeft - whiteRect.groupSelector_.x),
height: Math.abs(ey - cnvDiv.offsetTop - whiteRect.groupSelector_.y)
}).setStroke({color: "blue", width: 3});
} else {
groupSelector = surface.createRect({
x: whiteRect.groupSelector_.x,
y: whiteRect.groupSelector_.y,
width: Math.abs(ex - cnvDiv.offsetLeft - whiteRect.groupSelector_.x),
height: Math.abs(ey - cnvDiv.offsetTop - whiteRect.groupSelector_.y)
}).setStroke({color: "blue", width: 3});
}
e.stopPropagation();
}
}
});
如果我按住鼠标事件所连接的形状/组(上例中的白色方块)中的鼠标左键并开始拖动,则按照我的拖动动作开始绘制框。当我释放鼠标时,有时盒子会消失,有时则不会。当它没有时,框会一直被绘制并跟随我拖动时定义的鼠标移动。
在jsFiddle中,如果你在画布下观看console.debug或段落记者,你会发现有时候释放鼠标时onmouseup不会触发(我也检查了鼠标,但是同样的问题)。如果onmouseup永远不会开火,onmousemove继续开火。如果再次单击,有时会触发完整的鼠标单击系列(向下,向上,单击和移动),然后使绘制的矩形消失。但有时候这种情况不会发生,并且onmousemove会继续射击。如果在拖动/ onmousemove变为“卡住”并且没有任何反应之后单击,则没有调试行或对这些事件的记者更改,因此就好像除了onmousemove之外的所有鼠标事件都被压制了。我尝试添加stopPropagation,stopImmediatePropagation和preventDefault,但这没有帮助。我也试过使用Dojo事件的停止,但这并没有改变行为。
为了重新绘制onmousemove中的方框,我尝试了'getShape - &gt;编辑属性 - &gt; setShape'以及删除形状并制作一个全新的形状;这些方法都没有解决问题,它们之间没有任何明显的差异。
我正在使用Dojo 1.8.3,这种情况发生在Chrome(v25)和Firefox(v19)中,Canvas或SVG都是渲染器。
思考?我错过了一些明显的东西吗?
答案 0 :(得分:0)
将其整理出来。问题是onmouseup事件,当您决定停止拖出时,可以在底层/附加形状或您正在拖动的形状上触发形状。它是随机的,取决于光标位置,但如果您的拖动没有偏移或延迟,则有利于绘制的形状。 (dojox / gfx中的Moveable.js和Mover.js指出了我正确的方向。)
我在尝试使其工作的过程中将我的盒子改为路径,这似乎表现更好,但没有必要。
关键是要创建一个通用的'onMouseUp'函数,然后从originator-shape的onmouseup和拖动的形状onmouseup调用它。我的例子很草率,但我希望它能说明问题。
jsFiddle:http://jsfiddle.net/n3KGY/1/
密码:
// General method to clear out a selector if
// one was being drawn.
var selectorMouseUp = function(e) {
reporter.innerHTML = "onmouseup";
isMouseDown = false;
whiteRect.groupSelector_ = null;
if(groupSelector) {
if(selectorUp) {
groupSelector.disconnect(selectorUp);
}
surface.remove(groupSelector);
groupSelector = null;
}
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
};
// Mouseup event for the background/workspace
whiteRect.connect("onmouseup",function(e){
selectorMouseUp(e);
});
// Make a selector as a path on the surface
// and attach a mouseup to it
var makeSelector = function(x,y,w,h) {
groupSelector = surface.createPath()
.moveTo(x,y)
.hLineTo(x+w).vLineTo(y+h).hLineTo(x).vLineTo(y)
.setStroke({color: "blue", width: 3})
.closePath();
// Attach the same mouseup method as the workspace/background
selectorUp = groupSelector.connect("onmouseup",function(e){
reporter.innerHTML = "onmouseup (selector)";
selectorMouseUp(e);
});
};
bigRect.connect("onmousemove",function(e){
if(isMouseDown) {
if(bigRect.groupSelector_) {
var ex = e.clientX;
var ey = e.clientY;
reporter.innerHTML = "dragging at " + ex+","+ey;
var downX = bigRect.groupSelector_.x;
var downY = bigRect.groupSelector_.y;
var leadingX = (ex - grn.offsetLeft < downX ? ex - grn.offsetLeft : downX);
var leadingY = (ey - grn.offsetTop < downY ? ey - grn.offsetTop : downY);
var selWidth = Math.abs(ex - grn.offsetLeft - downX);
var selHeight = Math.abs(ey - grn.offsetTop - downY);
if(groupSelector) {
// If there's already a selector being drawn, get rid of it.
groupSelector.disconnect(selectorUp);
surface.remove(groupSelector);
}
// Draw the current selector
makeSelector(leadingX,leadingY,selWidth,selHeight);
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
}
}
});