Как запустить событие наведения мыши при перетаскивании

Когда я перетаскиваю элемент поверх другого div на котором у меня есть событие mouseover, событие не срабатывает. Тем не менее, это работает, если я наведусь на него, не перетаскивая.

Есть ли способ обнаружить всплывающие события на элементе, если я перетяну на него другой элемент?

6 ответов

Решение

Вот пример использования координатного решения XY.

Рабочий пример на 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);

Во всех представленных ответах я не вижу самого простого и очевидного (возможно, я что-то упускаю в 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

Есть два основных способа сделать это:

  1. трек mousemove и реагировать на координаты х / у
  2. иметь прозрачную цель, которая имеет более высокую z-index чем перетащить контейнер

Первый вариант на самом деле вообще не использует событие mouseover, но даст вам тот же чистый результат.

Имейте в виду, что некоторые браузеры (то есть) не будут запускаться mouseover на прозрачных элементах, поэтому вы должны подделать его, установив прозрачное фоновое изображение или выбрав случайное изображение в качестве фона и разместив его вне элемента следующим образом:

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

Другое возможное решение проблемы, когда перетаскиваемый элемент блокирует событие hover или mouseenter на элементе под ним:

pointer-events: none;

Если это применяется к перетаскиваемому элементу, наведение должно по-прежнему работать с элементом ниже.

У jQuery-ui есть плагин для этого.

Плагин при использовании с перетаскиваемым элементом сработает dropover события, которые могут быть связаны с любым действием, которое вам требуется.

См ответ Mottie на этот вопрос (демо включено)

Немного изменив код, размещенный 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);

Нашел небольшую ошибку в примере с jsfiddle. Когда вы покидаете область перетаскивания вертикально, область перетаскивания все еще имеет класс "овероятно ".

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

Другие вопросы по тегам