マウスオーバーイベントが発生している別のdiv
に要素をドラッグすると、イベントがトリガーされません。ただし、ドラッグせずにカーソルを合わせると機能します。
要素の上に別のイベントをドラッグした場合、要素のホバーイベントを検出する方法はありますか?
X-Y座標ソリューションを使用した例を次に示します。
この例は改善できますが、出発点としては適しています。
マウスの位置を追跡し、ドロップ可能なオブジェクトの境界ボックス内にあるかどうかを確認します。したがって、それらのいずれかで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);
提示されたすべての回答で、最も単純で明白なものはわかりません(多分、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はドラッグオーバークラスのままになります
これを行うには、2つの基本的な方法があります。
mousemove
を追跡し、x/y座標に反応するz-index
が高い透明なターゲットがある最初のオプションは、実際にはマウスオーバーイベントをまったく使用しませんが、同じ結果になります。
一部のブラウザー(つまり)は透明な要素でmouseover
をトリガーしないことに注意してください。そのため、透明な背景画像を設定するか、ランダム画像を背景として設定し、要素の外側に配置することにより、偽造する必要がありますこの:
element {
background: url(/path/to/img) no-repeat -10000px 0;
}
jQuery-uiには ドロップ可能なプラグイン があります。
プラグインを ドラッグ可能な要素 と一緒に使用すると、dropover
イベントがトリガーされ、必要なアクションにバインドできます。
参照 この質問に対するモティーの回答 (デモが含まれています)
Jsfiddleの例に小さなバグが見つかりました。ドロップ領域を垂直に離れても、ドロップ領域には「somethinghover」クラスがまだあります。
これを交換
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");
}
これとともに:
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");
}
ドラッグされた要素がその下の要素のhoverイベントまたはmouseenterイベントをブロックしている場合の問題に対する別の可能な解決策:
pointer-events: none;
これがドラッグされた要素に適用される場合、ホバーはその下の要素で機能します。
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);