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 が「動かなくなった」後にクリックしても何も起こらない場合、これらのイベントのデバッグ行やレポーターへの変更はありません。stopPropagation、stopImmediatePropagation、preventDefault を追加しようとしましたが、役に立ちませんでした。

onmousemove でボックスを再描画するために、「getShape -> プロパティの編集 -> setShape」の両方を試し、形状を削除してまったく新しい形状を作成しました。これらの方法のどちらも問題を止めず、それらの間に大きな違いはありませんでした.

私は Dojo 1.8.3 を使用しています。これは Chrome (v25) と Firefox (v19) の両方で発生し、キャンバスまたは SVG をレンダラーとして使用します。

考え?ここで明らかな何かが欠けていますか?

4

1 に答える 1

0

Sorted it out. The problem is the onmouseup event when you decide to stop dragging out the shape can fire on the underlying/attached shape, or on the shape you're dragging. It's random, depending on the cursor position, but favors the drawn shape if you don't have an offset or delay in your drag. (Moveable.js and Mover.js in dojox/gfx pointed me in the right direction.)

I changed my box to a path in the course of trying to make it work, and this seems to perform better, but isn't necessary.

The key was to make a general 'onMouseUp' function, then call that from both the originator-shape's onmouseup as well as the dragged shape's onmouseup. My example is sloppy, but I hope it gets the point across.

jsFiddle: http://jsfiddle.net/n3KGY/1/

Key code:

// 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 に答える