2

HTML5 Canvas でのドラッグ機能の実装に問題があります。シーン グラフなどの欠如を理解しており、マウス イベントで四角形のドラッグを識別する方法を設定しました。

ただし、問題は、マウスがキャンバスを離れたときにマウス イベントが失われることです。キャンバスの外にドラッグしてマウス ボタンを離すと、コードは mouseup イベントを取得せず、それに応じてドラッグ ロジックを変更します。ドラッグしたオブジェクトは、再度ドラッグを開始するまでマウスに固定されたままになります。

fabric.jsにはこの問題はありませんが、ライブラリ内の関連するコードを特定できません。これはどのように行うのですか?

4

2 に答える 2

4

最初に boolean 変数 isMouseDragged を使用します。これは、mouseDown の後に true に設定され、mouseUp の後に false に設定されます (または後で説明する別のイベント)。

ドラッグはいくつかの方法で処理できます。

if (mouse['isMouseDragged']) {
   mouse['xUp'] = e.clientX - canvas.getBoundingClientRect().left;
   mouse['yUp'] = e.clientY - canvas.getBoundingClientRect().top;
   ...
  1. マウスアップで、ボタンを押して離したポイント (線として想像してください) と、マウス ポインターがあるキャンバスの端 (別の線として想像してください) の間の交点を計算します。これらの 2 つの線の交点として mouseUp の位置を置きます。

    // FIRST OPTION
    if (mouse['mode'] == mouse['INTERSECTION']) {
        if (!mouse['isMouseOver']) {
            var edgeIntersect = mouseDraggedOut(mouse['xDown'], mouse['yDown'], mouse['xUp'], mouse['yUp']);
            mouse['xUp'] = edgeIntersect['x'];
            mouse['yUp'] = edgeIntersect['y'];
        }
    }
    
  2. キャンバス内で仮想マウス ポインター (座標) を保持します。

    // SECOND OPTION
    if (!mouse['isMouseOver']) {
        if (mouse['mode'] == mouse['LOCK_INSIDE']) {
            var edgeIntersect = mouseDraggedOut(canvas.width / 2, canvas.height / 2, mouse['x'], mouse['y']);
            mouse['x'] = edgeIntersect['x'];
            mouse['y'] = edgeIntersect['y'];
        }
    }
    
  3. キャンバスの外に出るときに座標を onMouseUp = onMouseOut にして、isMouseDragged を false に設定します。

    // THIRD OPTION
    if (mouse['isMouseDragged']) {
       if (mouse['mode'] == mouse['MOUSEOUT_POS']) {
          mouse['xUp'] = mouse['xOut'];
          mouse['yUp'] = mouse['yOut'];
          mouse['isMouseDragged'] = false;
       }
    }
    

キャンバスのエッジの交差を計算するには:

function mouseDraggedOut(x1, y1, x2, y2) {
// x1,y1 = mouseDown;  x2,y2 = mouseUp

var x3, y3, x4, y4;
var thisX, thisY;

if (x2 < 0) {// left edge
    x3 = 0;
    y3 = 0;
    x4 = 0;
    y4 = canvas.height;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));

    // I must do this for other checks, else corners (when two conditions are true) couldn't be handled
    // So I'll handle it one after another
    x2 = thisX;
    y2 = thisY;
}

if (x2 > canvas.width - 1) {// right edge
    x3 = canvas.width - 1;
    y3 = 0;
    x4 = canvas.width - 1;
    y4 = canvas.height - 1;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));
    x2 = thisX;
    y2 = thisY;
}

if (y2 < 0) {// top edge
    x3 = 0;
    y3 = 0;
    x4 = canvas.width - 1;
    y4 = 0;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));
    x2 = thisX;
    y2 = thisY;
}

if (y2 > canvas.height - 1) {// bottom edge
    x3 = 0;
    y3 = canvas.height - 1;
    x4 = canvas.width - 1;
    y4 = canvas.height - 1;
    thisX = Math.round(x1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (x2 - x1));
    thisY = Math.round(y1 + (((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))) * (y2 - y1));
}

return {
    'x' : thisX,
    'y' : thisY
};

}

ソースコードを見てください: http://jsfiddle.net/WolfeSVK/s2tNr/

于 2013-06-02T19:19:47.183 に答える