如何在拖动时启动鼠标悬停事件

时间:2011-12-23 09:08:30

标签: javascript jquery hover draggable

当我将一个元素拖到我有鼠标悬停事件的另一个div上时,该事件不会触发。但是,如果我将鼠标悬停在它上面而不拖动它就可以了。

如果我在元素上拖动另一个事件,有没有办法检测元素上的悬停事件?

7 个答案:

答案 0 :(得分:13)

以下是使用X-Y坐标解决方案的示例。

Working example on 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);

答案 1 :(得分:8)

在所有提出的答案中,我都没有看到最简单明了的答案(也许我在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会留在dragover类

答案 2 :(得分:3)

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

  1. 跟踪mousemove并对x / y坐标做出反应
  2. 具有比拖动容器
  3. 更高z-index的透明目标

    第一个选项根本没有真正使用鼠标悬停事件,但会给你相同的净结果。

    请注意,某些浏览器(即)不会在透明元素上触发mouseover,因此您必须通过设置透明的背景图像或将随机图像设置为背景并将其定位在透明元素之外来伪造它像这样的元素:

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

答案 3 :(得分:1)

jQuery-ui有一个droppable plugin

该插件与draggable element一起使用时会触发dropover个事件,这些事件可以绑定到您需要的任何操作。

请参阅Mottie's answer to this question(包含演示)

答案 4 :(得分:0)

修改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);

答案 5 :(得分:0)

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

答案 6 :(得分:0)

被拖动的元素何时阻止其下元素上的悬停或mouseenter事件的问题的另一种可能的解决方法:

pointer-events: none;

如果将其应用于拖动的元素,则悬停仍应作用于下方的元素。