以编程方式检测元素是否能够被悬停

Programatically detect whether an element is able to be be hovered or not

使用小书签我想使用 jquery.hover() 将 img 元素与 mouseenter 和 mouseleave 事件的处理程序绑定,但在某些情况下永远不会触发鼠标事件,因为 img 元素是尽管图像实际上是可见的,但以某种方式隐藏在鼠标之外:一个简单的例子是当 被透明元素重叠时。如果您使用像 firebug 检查器这样的工具,您会发现很多这样的例子。

我怎样才能弄清楚这种行为?理想情况下,我想构建一个函数,该函数将 return 为真或假,具体取决于元素是否可悬停。

感谢大家

问题:

真正的问题是覆盖一个元素的方法太多了。例如,该元素是否被其他 4 个元素覆盖,并且只是在中间打开了一个 space?我的意思的例子:

假设红色框是有问题的元素,正中间的小框是直接查看元素。

由于这些问题,可以非常"expensive"确定元素是否有可悬停区域。

解决方法:

我想出了一个使用 boundingClientRectdocument.elementFromPoint 和文档滚动的解决方案。它尝试通过检查相关元素的 4 个角来快速确定,然后如果返回错误,则开始通过确定的 "accuracy".

检查整个元素

更新:

我添加了一种方法来检查甚至不在视口中的元素。这是通过尝试滚动元素,运行 进行检查,然后滚动回检查开始前的前一个位置来实现的。这种情况发生得如此之快,以至于没有发生可见的跳跃。

function getOffset(el) {
    el = el.getBoundingClientRect();
    return {
        left: el.left + window.scrollX,
        top: el.top + window.scrollY
    }
}

function isElementHoverable(element) {
    var pageX = window.scrollX;
    var pageY = window.scrollY;
    var elementXY = getOffset(element);
    var accuracy = 1;
    var canBeHovered = false;

    window.scrollTo(elementXY.left, elementXY.top);

    var box = element.getBoundingClientRect();

    // try the 4 corners first
    if (
        element == document.elementFromPoint(box.left, box.top) ||
        element == document.elementFromPoint(box.left, box.bottom - 1) ||
        element == document.elementFromPoint(box.right - 1, box.top) ||
        element == document.elementFromPoint(box.right - 1, box.bottom - 1)
    ) {
        canBeHovered = true;
    }

    loop1:
        for (let i = box.left; i < box.right; i += accuracy) {
            for (let j = box.top; j < box.bottom; j += accuracy) {
                if (element == document.elementFromPoint(i, j)) {
                    canBeHovered = true;
                    break loop1;
                }
            }
        }

    window.scrollTo(pageX, pageY); // Scroll back to the original position
    return canBeHovered;
}

I worked up an actual example on JSFiddle(示例已更新以反映页面向下滚动的元素),完成几个测试。您需要打开浏览器控制台才能查看测试结果。您可能还想先在 Chrome 或 Firefox 中测试它,因为我没有在其他地方测试它。


需要记住的几件事:

如果 4 个角检查失败,则检查元素的其余部分会变得昂贵。 "accuracy" 数字越小,价格越高。该数字决定了 运行 检查的频率。所以如果精度是1,那么它会每1px检查一次。如果数字是 10,那么它将在 X 和 Y 轴上每 10px 检查一次。

需要注意的是,几乎没有办法知道页面中元素的变化。您在评论中提到,某些元素可能会消失 "blocking" 在检查期间,但不会在用户交互时消失。没有 AI 就无法知道此功能。但是,此函数应根据您的选择调用,而不仅仅是在页面加载时调用。