拖动时如何在事件上启动鼠标

How to start mouseover event while dragging

本文关键字:启动 鼠标 事件 拖动      更新时间:2023-09-26

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

是否有一种方法来检测悬停事件上的一个元素,如果我拖动另一个在它?

在所有给出的答案中,我没有看到最简单和明显的一个(也许我在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将停留在拖拽类

下面是一个使用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);

有两种基本方法:

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

第一个选项根本没有真正使用mouseover事件,但会给你相同的最终结果。

请注意,有些浏览器(例如)不会触发mouseover透明元素,所以你必须通过设置一个透明的背景图像或设置一个随机图像作为背景,并将其定位在元素的外部,像这样:

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

jQuery-ui有一个可放下的插件。

插件,当与可拖动元素一起使用时,将触发dropover事件,该事件可以绑定到您需要的任何操作。

参见motie对这个问题的回答(包括演示)

稍微修改一下emrahgunduz发布的代码,特别是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);

另一种可能的解决方案是当拖动的元素阻塞其下元素的hover或mouseenter事件时:

pointer-events: none;

如果这个应用于被拖动的元素,那么悬停应该仍然在下面的元素上工作。

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