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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:44:09  来源:igfitidea点击:

How to start mouseover event while dragging

javascriptjqueryhoverdraggable

提问by V.Rashkov

When I drag an element over another divon 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 坐标解决方案的示例。

Working example on jsfiddle

jsfiddle 上的工作示例

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:

有两种基本方法可以做到这一点:

  1. track mousemoveand react to x/y coordinates
  2. have a transparent target that has a higher z-indexthan the drag container
  1. 跟踪mousemove并响应 x/y 坐标
  2. 有一个高于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 mouseoveron 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.

jQuery-ui 有一个放置的插件

The plugin, when used with a draggable elementwill trigger dropoverevents, 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' 类。

http://jsfiddle.net/MAazv

http://jsfiddle.net/MAazv

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");
}

http://jsfiddle.net/MAazv/122

http://jsfiddle.net/MAazv/122

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.

如果这应用于拖动的元素,则悬停应该仍然适用于下方的元素。