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

时间:2015-06-01 18:27:53

标签: javascript jquery events mouseleave mouseout

标准mouseout事件的一个问题是它不仅在光标离开由元素的外部边界限制的屏幕区域时触发,而且当光标悬停在某个其他元素上时触发包含在这个范围内。

jQuery的mouseleave事件的基本原理是仅在光标离开由元素的外部边界限定的区域时发出 的信号。

不幸的是,这似乎只有在"阻碍"元素是"阻碍"的后代。元件。如果"阻碍"元素是通过绝对定位的地方,然后当鼠标悬停在它上面时,{&#34}上的mouseleave事件被阻塞了#34;元素被解雇了。

例如,使用以下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不是,但是,我们可以将其设置为“#{1}}。妨碍&#34; #b-div都是一样的。这在this jsFiddle。

中有说明

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

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

...然后将鼠标悬停在#b-div的外围区域会导致蓝色轮廓显示在此周边,除非鼠标悬停在#c-div以上

使用#b-div#c-div获得与mouseleave#b-div达到同样效果的方法#d-divmouseover

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

2 个答案:

答案 0 :(得分:7)

根据您#c-div完全包含#b-div的{​​{1}}的初始帖子,这样做了:

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

Fiddle 1

<小时/> 由于#c-div可能并非始终完全包含#b-div,因此如果您添加此样式,则可以使用现有代码:

#c-div {
  pointer-events: none;
}

但这样就无法使用鼠标与#c-div进行交互。

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

Fiddle 3

答案 1 :(得分:0)

如果您无法使用Rich的Template.singleComment.helpers({ momentTime: function () { return moment(this.createdAt).fromNow(); }, byWho: function(){ user = Meteor.users.findOne({_id: this.createdBy}) if(user){ return user.username; } else { return this.createdBy; } } }) 建议(也许您需要support IE 10,或者您确实需要与绝对定位的div进行互动),您可以手动检查事件不会pointer-events: none使用relatedTarget

但是,您还必须检查#c-div中的鼠标距离是否不会#c-div

&#13;
&#13;
#b-div
&#13;
$( '#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' );
    }
});
&#13;
#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;
}
&#13;
&#13;
&#13;