是否有一个快速和简单的方法来做到这一点在jQuery,我错过了?

我不想使用鼠标悬停事件,因为我已经将它用于其他事情。我只需要知道鼠标在给定时刻是否在某个元素上。

我想做一些这样的事情,如果有一个“IsMouseOver”函数:

function hideTip(oi) {
    setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}

当前回答

使用 evt.originalEvent.composedPath()

MouseEvent给出了鼠标最近与之交互的HTMLElement的数组。最后一个元素是最外层的(也就是说,它总是Window)。

MouseEvent composedPath()示例如下:

通过检查该数组中是否存在可点击的元素,您将知道是否在特定元素上有鼠标悬停…

$(window).on("mouseup", onMouseUp);
const $someButton = $("a.yourButton");

function onMouseUp(evt) {
  const path = evt.originalEvent.composedPath();
  if(path.indexOf($someButton[0]) !== -1){
    // released mouse over button
  }else{
    // did not release mouse over button
  }
}

其他回答

在鼠标退出时设置超时以淡出并将返回值存储为对象中的数据。然后onmouseover,如果数据中有值,取消超时。

删除淡出的回调数据。

使用mouseenter/mouseleave实际上成本更低,因为当child鼠标悬停/鼠标退出触发时,它们不会触发菜单。

For those like me who needed an answer that didn't depend on browser mouse-over/enter/leave events or hover states. I had a situation in a home-page slider, the left and right slide click areas could overlap (or sometimes completely cover) the CTA buttons in the banner - this renders all those previous methods useless (browser only reports events on the element with the highest z-index). I was tasked with making the click event care more about the button than the banner functionality when the click is over the button.

我的完整解是这样的:

jQuery('.carousel-control-prev').on('click.testClick', function(e) {
    var bannerButtons = jQuery('.banner-content a');
    for (var i = 0; i < bannerButtons.length; i++) {
        if (isMouseOver(bannerButtons.eq(i), e)) {
            e.preventDefault();
            e.stopPropagation();
            bannerButtons[i].click();
        }
    }
});

function isMouseOver($el, e) {
    if ($el.is(':visible')) {
        var offset = $el.offset();
        var x = (e.pageX - offset.left);
        var y = (e.pageY - offset.top);
        if (x > 0 && x < $el.outerWidth() && y > 0 && y < $el.outerHeight()) {
            return true;
        }
    }
    return false;
}

这可能需要更多的工作和测试,但现在它做了我需要的-在这种情况下是拦截横幅左键点击,检查鼠标是否恰好在CTA按钮上,如果是,点击CTA而不是横幅导航。

我完全理解更好的解决方案是重新设计横幅区域,这样就不会发生这种情况,但设计超出了我的控制范围。

我结合了这个主题的想法,想出了这个,这对于显示/隐藏子菜单很有用:

$("#menu_item_a").mouseenter(function(){
   clearTimeout($(this).data('timeoutId'));
   $("#submenu_a").fadeIn("fast");
}).mouseleave(function(){
   var menu_item = $(this);

   var timeoutId = setTimeout(function(){
      if($('#submenu_a').is(':hover'))
      {
        clearTimeout(menu_item.data('timeoutId'));
      }
      else
      {
        $("#submenu_a").fadeOut("fast");
      }
   }, 650);

    menu_item.data('timeoutId', timeoutId); 
});

 $("#submenu_a").mouseleave(function(){
   $(this).fadeOut("fast");
 });

似乎对我有用。希望这能帮助到一些人。

编辑:现在意识到这种方法在IE中不能正确工作。

一个干净优雅的悬停检查:

if ($('#element:hover').length != 0) {
    // do something ;)
}

我不能使用上面的任何建议。 为什么我更喜欢我的解决方案? 此方法检查鼠标是否在您所选择的任何时间停留在元素上。 Mouseenter和:hover很酷,但是Mouseenter只在你移动鼠标时触发,而不是当元素在鼠标下移动时触发。 :盘旋很可爱,但是…即

所以我这样做:

没有1。每次鼠标移动时,存储鼠标x, y位置, 没有2。检查鼠标是否在任何匹配查询的元素上…比如触发mouseenter事件

// define mouse x, y variables so they are traced all the time
var mx = 0; //  mouse X position
var my = 0; //  mouse Y position

// update mouse x, y coordinates every time user moves the mouse
$(document).mousemove(function(e){
    mx = e.pageX;
    my = e.pageY;
});

// check is mouse is over an element at any time You need (wrap it in function if You need to)
$("#my_element").each(function(){
    boxX = $(this).offset().left;
    boxY = $(this).offset().top;
    boxW = $(this).innerWidth();
    boxH = $(this).innerHeight();
    if ((boxX <= mx) &&
        (boxX + 1000 >= mx) &&
        (boxY <= my) &&
        (boxY + boxH >= my))
    {
        // mouse is over it so you can for example trigger a mouseenter event
        $(this).trigger("mouseenter");
    }
});