0

我正在尝试使用 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 不会触发(我也检查了 mouseup,但这有同样的问题)。在 onmouseup 从不触发的情况下, onmousemove 会继续触发。如果再次单击,有时会触发完整的鼠标单击系列(向下、向上、单击和移动),然后使绘制的矩形消失。但是,有时这不会发生,并且 onmousemove 会继续触发。如果在拖动/onmousemove 变为“卡住”之后单击并且没有任何反应,则这些事件没有调试行或对报告器的更改,因此就好像除 onmousemove 之外的所有鼠标事件都被压制了。我尝试添加 stopPropagation、stopImmediatePropagation 和 preventDefault,但这没有帮助。

为了在 onmousemove 中重新绘制框,我尝试了 'getShape -> edit properties -> setShape' 以及删除形状并制作了一个全新的形状;这些方法都没有解决问题,并且它们之间没有任何明显的区别。

我使用的是 Dojo 1.8.3,这发生在 Chrome (v25) 和 Firefox (v19) 中,使用 Canvas 或 SVG 作为渲染器。

想法?我在这里遗漏了一些明显的东西吗?

4

1 回答 1

0

整理出来。问题是当您决定停止拖出形状时的 onmouseup 事件可能会在基础/附加形状或您正在拖动的形状上触发。它是随机的,取决于光标位置,但如果您的拖动没有偏移或延迟,则有利于绘制的形状。(dojox/gfx 中的 Moveable.js 和 Mover.js 为我指明了正确的方向。)

我在尝试使其工作的过程中将我的盒子更改为一条路径,这似乎表现更好,但不是必需的。

关键是创建一个通用的“onMouseUp”函数,然后从创建者形状的 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();
        }
    }
});
于 2013-03-01T00:33:47.693 回答