如何通过绝对定位的非后代实现鼠标效果?

kjo*_*kjo 6 javascript jquery events mouseleave mouseout

标准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>
Run Code Online (Sandbox Code Playgroud)

... #d-div是一个真正的后代#b-div,而#c-div不是,但是,但我们可以设计它,使它"阻碍" #b-div所有相同.这在这个 jsFiddle中有说明.

如果现在定义以下事件#b-div:

$( '#b-div' ).bind( {
    mouseenter: function () {
        $( this ).addClass( 'outlined' );
    },
    mouseleave: function () {
        $( this ).removeClass( 'outlined' );
    }
} );
Run Code Online (Sandbox Code Playgroud)

...然后将鼠标悬停在#b-div外围周围会导致在此周边出现蓝色轮廓,除非鼠标结束#c-div.

有没有办法让具有相同的效果#b-div,并#c-divmouseleave与实现#b-div#d-div

编辑:我已经修复了jsFiddle中显示的示例.该示例的原始版本显示了不具代表性的特殊情况,其中所有阻碍元素与受阻元素重叠.在这种特殊情况下,可以通过在阻碍元件和阻塞元件上定义相同的事件来模拟期望的效果,因此,实际上,将阻碍元件转变为阻塞元件的补片.当阻碍元件未完全包含在受阻元件的外周边内时,这将不起作用(如修正后的jsFiddle所示).更一般地,基于在mouseover阻碍元件上使用事件的任何解决方案必然会失败,因为真正的问题是防止(或使无效)mouseleave对受阻元件的假.

Ric*_*ock 7

这样做,基于您的初始帖子#c-div完全包含在#b-div:

$('#b-div, #c-div').on( {
  mouseenter: function (ev) {
    $('#b-div').addClass('outlined');
  },
  mouseleave: function (ev) {
    $('#b-div').removeClass('outlined');
  }
});
Run Code Online (Sandbox Code Playgroud)

小提琴1


由于#c-div可能并非总是完全包含在内#b-div,因此如果添加此样式,则可以使用现有代码:

#c-div {
  pointer-events: none;
}
Run Code Online (Sandbox Code Playgroud)

但这将使得无法与#c-div使用鼠标进行交互.

小提琴2


如果你确实需要与之交互#c-div,并且它不完全在内#b-div,你可以像这样使用Element.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
    )
  }
);
Run Code Online (Sandbox Code Playgroud)

小提琴3