Javascript 如何在拖动时启动鼠标悬停事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8614073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to start mouseover event while dragging
提问by V.Rashkov
When I drag an element over another div
on which I have a mouseover event, the event doesn't trigger. However, it works if I hover over it without dragging.
当我将一个元素拖到另一个div
我有鼠标悬停事件的元素上时,该事件不会触发。但是,如果我将鼠标悬停在它上面而不拖动它就可以工作。
Is there a way to detect hover events on an element if I drag another one over it?
如果我将另一个悬停事件拖到元素上,有没有办法检测元素上的悬停事件?
采纳答案by emrahgunduz
Here is an example using the X-Y coordinate solution.
这是一个使用 XY 坐标解决方案的示例。
The example can be improved, but is a good starting point.
该示例可以改进,但它是一个很好的起点。
Simply keeps track of the mouse location and checks if it appears to be inside any bounding boxes of the droppable objects. Hence, if the mouseup event fires on any one of them, dragged object is dropped.
只需跟踪鼠标位置并检查它是否出现在可放置对象的任何边界框内。因此,如果 mouseup 事件在其中任何一个上触发,则拖动的对象将被丢弃。
You can also use the coordinates of the object you are dragging for detecting if its on a droppable box, but it requires a little more code for finding the bounding box coords and using the mouse is enough for me.
您还可以使用您拖动的对象的坐标来检测它是否位于可放置的框上,但是它需要更多的代码来查找边界框坐标并且使用鼠标对我来说就足够了。
The code uses jQuery but no jQueryUI. I tested in Chrome, Firefox and Opera, but not IE :)
代码使用 jQuery 但没有 jQueryUI。我在 Chrome、Firefox 和 Opera 中测试过,但没有在 IE 中测试过 :)
I'm also adding the code to here if jsfiddle is not accessible.
如果 jsfiddle 不可访问,我也会将代码添加到此处。
HTML
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
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
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);
回答by Wolf War
In all presented answers, I don't see the most simple and obvious one (maybe I'm missing something in OP question). But, if someone stumble upon this later, and needs fast and simple solution in pure JS..
在所有提出的答案中,我没有看到最简单和最明显的答案(也许我在 OP 问题中遗漏了一些东西)。但是,如果有人后来偶然发现了这一点,并且需要在纯 JS 中快速而简单的解决方案。
You do it by changing element className ondragover, and changing back to original class ondragleave
您可以通过更改元素 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
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
}
edit:
forgot to mention, you need to bring back original class ondroptoo, otherwise div will stay in dragover class
编辑:
忘了提,你需要带回原班ondrop太多,否则格将留在的dragover类
回答by Martin Jespersen
There are two basic ways you can do this:
有两种基本方法可以做到这一点:
- track
mousemove
and react to x/y coordinates - have a transparent target that has a higher
z-index
than the drag container
- 跟踪
mousemove
并响应 x/y 坐标 - 有一个高于
z-index
拖动容器的透明目标
First option doesn't really use the mouseover event at all, but will give you the same net result.
第一个选项根本没有真正使用鼠标悬停事件,但会给你相同的最终结果。
Be aware that some browsers (ie) won't trigger mouseover
on transparent elements, so you have to fake it by setting a background image that is transparent or setting a random image as background and positioning it outside the element like this:
请注意,某些浏览器(即)不会mouseover
在透明元素上触发,因此您必须通过设置透明的背景图像或将随机图像设置为背景并将其放置在元素外部来伪造它,如下所示:
element {
background: url(/path/to/img) no-repeat -10000px 0;
}
回答by willscripted
jQuery-ui has a droppable pluginfor this.
The plugin, when used with a draggable elementwill trigger dropover
events, which can be bound to any action you require.
该插件与可拖动元素一起使用时将触发dropover
事件,该事件可以绑定到您需要的任何操作。
See Mottie's answer to this question(demo included)
请参阅Mottie 对此问题的回答(包括演示)
回答by gigaDIE
Modifing a bit the code posted by emrahgunduz, specifically the for loop, you can also manage nested droppable area.
稍微修改一下emrahgunduz贴的代码,特别是for循环,还可以管理嵌套的droppable区域。
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);
回答by Totolicious
Found a small bug in the jsfiddle example. When you leave the drop area vertically, the drop area still has the 'somethinghover' class.
在 jsfiddle 示例中发现了一个小错误。当您垂直离开放置区域时,放置区域仍然具有 'somethinghover' 类。
Replace this
替换这个
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");
}
with this:
有了这个:
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");
}
回答by Paulsarms
Another possible solution to the problem of when the dragged element is blocking the hover or mouseenter event on the element under it:
另一个可能的解决方案是当被拖动的元素在其下的元素上阻塞了 hover 或 mouseenter 事件时:
pointer-events: none;
pointer-events: none;
If this is applied to the dragged element then hover should still work on the element beneath.
如果这应用于拖动的元素,则悬停应该仍然适用于下方的元素。