web-dev-qa-db-ja.com

ドラッグ中にマウスオーバーイベントを開始する方法

マウスオーバーイベントが発生している別のdivに要素をドラッグすると、イベントがトリガーされません。ただし、ドラッグせずにカーソルを合わせると機能します。

要素の上に別のイベントをドラッグした場合、要素のホバーイベントを検出する方法はありますか?

27
V.Rashkov

X-Y座標ソリューションを使用した例を次に示します。

jsfiddleの使用例

この例は改善できますが、出発点としては適しています。

マウスの位置を追跡し、ドロップ可能なオブジェクトの境界ボックス内にあるかどうかを確認します。したがって、それらのいずれかでmouseupイベントが発生した場合、ドラッグされたオブジェクトはドロップされます。

ドラッグ可能なオブジェクトの座標を使用して、ドロップ可能なボックス上にあるかどうかを検出することもできますが、境界ボックスの座標を見つけてマウスを使用するだけで十分です。

コードはjQueryを使用しますが、jQueryUIは使用しません。私はChrome、Firefox、Operaでテストしましたが、IE :)はテストしていません

Jsfiddleにアクセスできない場合は、ここにもコードを追加しています。

HTML

<p>Drag orange boxes to grey ones</p>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>
<div class="droppable"></div>

<div class="draggable"></div>
<div class="draggable"></div>
<div class="draggable"></div>

CSS

.droppable {
    width:50px;
    height:50px;
    float: left;
    background-color: #DDD;
    margin: 5px;
}

.draggable {
    width:40px;
    height:40px;
    float: right;
    background-color: #FC0;
    margin: 5px;
    cursor: pointer;
}

.dropped {
    background-color: #FC0;
}

.somethingover {
    background-color: #FCD;
}

JS

var dragged, mousex, mousey, coordinates = [];

var continueDragging = function(e) {
    // Change the location of the draggable object
    dragged.css({
        "left": e.pageX - (dragged.width() / 2),
        "top": e.pageY - (dragged.height() / 2)
    });

    // Check if we hit any boxes
    for (var i in coordinates) {
        if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
            if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
                // Yes, the mouse is on a droppable area
                // Lets change the background color
                coordinates[i].dom.addClass("somethingover");
            }
        } else {
            // Nope, we did not hit any objects yet
            coordinates[i].dom.removeClass("somethingover");
        }
    }

    // Keep the last positions of the mouse coord.s
    mousex = e.pageX;
    mousey = e.pageY;
}

var endDragging = function(e) {
    // Remove document event listeners
    $(document).unbind("mousemove", continueDragging);
    $(document).unbind("mouseup", endDragging);

    // Check if we hit any boxes
    for (var i in coordinates) {
        if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
            if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
                // Yes, the mouse is on a droppable area
                droptarget = coordinates[i].dom;
                droptarget.removeClass("somethingover").addClass("dropped");
                dragged.hide("fast", function() {
                    $(this).remove();
                });
            }
        }
    }

    // Reset variables
    mousex = 0;
    mousey = 0;
    dragged = null;
    coordinates = [];
}

var startDragging = function(e) {
    // Find coordinates of the droppable bounding boxes
    $(".droppable").each(function() {
        var lefttop = $(this).offset();
        // and save them in a container for later access
        coordinates.Push({
            dom: $(this),
            left: lefttop.left,
            top: lefttop.top,
            right: lefttop.left + $(this).width(),
            bottom: lefttop.top + $(this).height()
        });
    });

    // When the mouse down event is received
    if (e.type == "mousedown") {
        dragged = $(this);
        // Change the position of the draggable
        dragged.css({
            "left": e.pageX - (dragged.width() / 2),
            "top": e.pageY - (dragged.height() / 2),
            "position": "absolute"
        });
        // Bind the events for dragging and stopping
        $(document).bind("mousemove", continueDragging);
        $(document).bind("mouseup", endDragging);
    }
}

// Start the dragging
$(".draggable").bind("mousedown", startDragging);
13
emrahgunduz

提示されたすべての回答で、最も単純で明白なものはわかりません(多分、OPの質問に何か欠けています)。しかし、誰かが後でこれに遭遇し、純粋なJSで高速かつシンプルなソリューションが必要な場合。

要素className ondragoverを変更し、元のクラスondragleaveに戻すことによって、それを行います

my_element.ondragover = function(ev) {  
 ev.preventDefault();  
 this.className = 'myElem_dragover';  
}  
my_element.ondragleave = function(ev) {  
 ev.preventDefault();  
 this.className = 'myElem_orig';  
}

[〜#〜] css [〜#〜]

.myElem_orig {     //this is your initial class for element
  top: 30px;
  left: 20px;
  .....
  background-color: blue;  
}  

.myElem_orig:hover {   //this is hover state, just changing bg color
  background-color: red;
}

.myElem_dragover { //new class, needs all attributes from original class
  top: 30px;
  left: 20px;
  ........ 
  background-color: red; //behaves the same like hover does
}

編集:
言及するのを忘れた場合、元のクラスを戻す必要がありますondrop、そうしないと、divはドラッグオーバークラスのままになります

8
Wolf War

これを行うには、2つの基本的な方法があります。

  1. mousemoveを追跡し、x/y座標に反応する
  2. ドラッグコンテナよりもz-indexが高い透明なターゲットがある

最初のオプションは、実際にはマウスオーバーイベントをまったく使用しませんが、同じ結果になります。

一部のブラウザー(つまり)は透明な要素でmouseoverをトリガーしないことに注意してください。そのため、透明な背景画像を設定するか、ランダム画像を背景として設定し、要素の外側に配置することにより、偽造する必要がありますこの:

element {
 background: url(/path/to/img) no-repeat -10000px 0;
}
3

jQuery-uiには ドロップ可能なプラグイン があります。

プラグインを ドラッグ可能な要素 と一緒に使用すると、dropoverイベントがトリガーされ、必要なアクションにバインドできます。

参照 この質問に対するモティーの回答 (デモが含まれています)

1
will-ob

Jsfiddleの例に小さなバグが見つかりました。ドロップ領域を垂直に離れても、ドロップ領域には「somethinghover」クラスがまだあります。

http://jsfiddle.net/MAazv

これを交換

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
  if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
    // Yes, the mouse is on a droppable area
    // Lets change the background color
    coordinates[i].dom.addClass("somethingover");
  }
} else {
  // Nope, we did not hit any objects yet
  coordinates[i].dom.removeClass("somethingover");
}

http://jsfiddle.net/MAazv/122

これとともに:

if (mousex >= coordinates[i].left && mousex <= coordinates[i].right && mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
  // Yes, the mouse is on a droppable area
  // Lets change the background color
  coordinates[i].dom.addClass("somethingover");
} else {
  // Nope, we did not hit any objects yet
  coordinates[i].dom.removeClass("somethingover");
}
0
Totolicious

ドラッグされた要素がその下の要素のhoverイベントまたはmouseenterイベントをブロックしている場合の問題に対する別の可能な解決策:

pointer-events: none;

これがドラッグされた要素に適用される場合、ホバーはその下の要素で機能します。

0
Paulsarms

Emrah gunduzによって投稿されたコード、特にforループを少し変更すると、ネストされたドロップ可能領域を管理することもできます。

var dragged, mousex, mousey, coordinates = [];

var continueDragging = function(e) {
    // Change the location of the draggable object
    dragged.css({
        "left": e.pageX - (dragged.width() / 2),
        "top": e.pageY - (dragged.height() / 2)
    });

    // Check if we hit any boxes
    for (var i = coordinates.length - 1; i >= 0; i--) {
        if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
            if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
                // Yes, the mouse is on a droppable area
                // Lets change the background color
                $('.droppable').removeClass("somethingover");
                coordinates[i].dom.addClass("somethingover");
                break;
            }
        } else {
            // Nope, we did not hit any objects yet
            coordinates[i].dom.removeClass("somethingover");
        }
    }

    // Keep the last positions of the mouse coord.s
    mousex = e.pageX;
    mousey = e.pageY;
};

var endDragging = function(e) {
    // Remove document event listeners
    $(document).unbind("mousemove", continueDragging);
    $(document).unbind("mouseup", endDragging);

    // Check if we hit any boxes
    for (var i = coordinates.length - 1; i >= 0; i--) {
        if (mousex >= coordinates[i].left && mousex <= coordinates[i].right) {
            if (mousey >= coordinates[i].top && mousey <= coordinates[i].bottom) {
                // Yes, the mouse is on a droppable area
                droptarget = coordinates[i].dom;
                droptarget.removeClass("somethingover").addClass("dropped");
                dragged.hide("fast", function() {
                    $(this).remove();
                });
            }
        }
    }

    // Reset variables
    mousex = 0;
    mousey = 0;
    dragged = null;
    coordinates = [];
};

var startDragging = function(e) {
    // Find coordinates of the droppable bounding boxes
    $(".droppable").each(function() {
        var lefttop = $(this).offset();
        // and save them in a container for later access
        coordinates.Push({
        dom: $(this),
        left: lefttop.left,
        top: lefttop.top,
        right: lefttop.left + $(this).width(),
        bottom: lefttop.top + $(this).height()
    });
};

// When the mouse down event is received
if (e.type == "mousedown") {
    dragged = $(this);
    // Change the position of the draggable
    dragged.css({
        "left": e.pageX - (dragged.width() / 2),
        "top": e.pageY - (dragged.height() / 2),
        "position": "absolute"
    });
    // Bind the events for dragging and stopping
    $(document).bind("mousemove", continueDragging);
    $(document).bind("mouseup", endDragging);
}

// Start the dragging
$(".draggable").bind("mousedown", startDragging);
0
gigaDIE