Как добиться эффекта mouseleave с абсолютно позиционируемого не потомки?
одна проблема со стандартным mouseout
событие заключается в том, что оно срабатывает не только тогда, когда курсор покидает область экрана, ограниченную внешним периметром элемента, но и когда курсор парит над каким-либо другим элементом, содержащимся в этом периметре.
обоснование для jQuery mouseleave
событие-это сигнал только момент, когда курсор покидает область, ограниченную внешним периметром элемента.
к сожалению, это, кажется, работать только в том случае, если" препятствующий "элемент является потомком" препятствующего " элемента. Если" препятствующий " элемент находится там, где он находится через абсолютное позиционирование, то когда мышь парит над ним,mouseleave
событие на" препятствуют " элемент получает уволен.
например, со следующим HTML-кодом:
<div id="b-div">
<div id="d-div"><span>d</span></div>
</div>
<div id="c-div"><span>c</span></div>
...#d-div
является истинным потомком #b-div
, а #c-div
нет, но, но мы можем стиль его так, что он "мешает"#b-div
все то же самое. Это проиллюстрировано в этой jsFiddle.
если теперь определить следующие события на #b-div
:
$( '#b-div' ).bind( {
mouseenter: function () {
$( this ).addClass( 'outlined' );
},
mouseleave: function () {
$( this ).removeClass( 'outlined' );
}
} );
...затем наведите курсор мыши внутри #b-div
внешний периметр заставляет синий контур появляться по этому периметру,если мышь находится над #c-div
.
есть ли способ, чтобы получить тот же эффект с #b-div
и #c-div
as mouseleave
достигает #b-div
и #d-div
?
EDIT: у меня исправлена пример в jsFiddle. Первоначальный вариант этого примера показал непредставительный частный случай, когда все препятствующие элементы перекрываются с препятствующими элементами. В этом частном случае желаемый эффект может быть имитация определяя одни и те же события как на препятствующих, так и на препятствующих элементах, таким образом, по сути, превращая препятствующий элемент в пятно препятствующего элемента. Это не будет работать, когда препятствующий элемент не полностью содержится в пределах внешнего периметра заблокированного элемента (как показано в измененном jsFiddle). В более общем плане, любое решение, основанное на использовании mouseover
событие на препятствующем элементе обязательно завершится неудачей, так как реальные проблема в том, чтобы предотвратить (или сделать неэффективным) ложное mouseleave
на заблокированном элементе.
2 ответов
это делает это, основываясь на вашем первоначальном посте, в котором #c-div
полностью содержался в #b-div
:
$('#b-div, #c-div').on( {
mouseenter: function (ev) {
$('#b-div').addClass('outlined');
},
mouseleave: function (ev) {
$('#b-div').removeClass('outlined');
}
});
С
#c-div
не всегда может содержаться полностью в #b-div
, вы можете использовать существующий код, если вы добавите этот стиль:
#c-div {
pointer-events: none;
}
но это сделает невозможным взаимодействие с #c-div
С помощью мыши.
если вы do необходимо взаимодействовать с #c-div
, и это не полностью в #b-div
, вы можете использовать элемент.getBoundingClientRect такой:
$('#b-div, #c-div').on('mousemove mouseleave',
function(ev) {
var br= $('#b-div')[0].getBoundingClientRect();
$('#b-div').toggleClass(
'outlined',
ev.pageX > br.left && ev.pageX < br.left+br.width &&
ev.pageY > br.top && ev.pageY < br.top +br.height
)
}
);
если вы не можете использовать предложения Рича pointer-events: none
(возможно, вам нужно поддержка IE 10 или вам нужно взаимодействовать с абсолютно позиционированных div-элемент), вы можете вручную проверить, что событие не будет #c-div
используя relatedTarget
.
однако, вы также должны проверить, что mouseleave от #c-div
не будет #b-div
.
$( '#b-div' ).bind( {
mouseenter: function () {
$( this ).addClass( 'outlined' );
},
mouseleave: function (e) {
if (e.relatedTarget.id == 'c-div' || $.contains(document.getElementById('c-div'), e.relatedTarget)) {
return;
}
$( this ).removeClass( 'outlined' );
}
} );
$( '#c-div' ).bind( {
mouseleave: function (e) {
if (e.relatedTarget.id == 'b-div' || $.contains(document.getElementById('b-div'), e.relatedTarget)) {
return;
}
$( '#b-div' ).removeClass( 'outlined' );
}
});
#a-div {
position: relative;
margin: 20px;
}
#b-div {
height: 100px;
width: 100px;
background-color: #555;
padding: 50px;
}
#c-div {
position: absolute;
height: 50px;
width: 200px;
top: 100px;
left: 100px;
background-color: #999;
}
#d-div {
height: 50px;
width: 50px;
background-color: #ddd;
text-align: center;
}
#c-div span {
margin: 21.5px;
line-height: 50px;
}
#d-div span {
margin: auto;
line-height: 50px;
}
.outlined {
outline: 10px solid steelblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a-div">
<div id="b-div"><div id="d-div"><span>d</span></div></div>
<div id="c-div"><span>c</span></div>
</div>