Как запустить событие наведения мыши при перетаскивании
Когда я перетаскиваю элемент поверх другого div
на котором у меня есть событие mouseover, событие не срабатывает. Тем не менее, это работает, если я наведусь на него, не перетаскивая.
Есть ли способ обнаружить всплывающие события на элементе, если я перетяну на него другой элемент?
6 ответов
Вот пример использования координатного решения XY.
Пример можно улучшить, но это хорошая отправная точка.
Просто отслеживает местоположение мыши и проверяет, находится ли она внутри каких-либо ограничивающих рамок объектов сбрасывания. Следовательно, если событие 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
Есть два основных способа сделать это:
- трек
mousemove
и реагировать на координаты х / у - иметь прозрачную цель, которая имеет более высокую
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. Когда вы покидаете область перетаскивания вертикально, область перетаскивания все еще имеет класс "овероятно ".
Замени это
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");
}
с этим:
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");
}