8

如何有效地找到位于指定查询元素之上的所有 DOM 元素?

也就是说,我想要一个 Javascript 函数,当我传入对 DOM 元素的引用时,它将返回与输入元素有非零重叠的所有 DOM 元素的数组,并在视觉上出现在它的上方。我的具体目标是找到那些可能在视觉上阻碍它们下方元素的元素。

上下文是我对网页、查询元素或其他任何东西都没有高级知识的上下文。元素可以出于多种原因出现在其他元素之上。

我当然可以通过对 DOM 进行详尽的搜索来做到这一点,但是当 DOM 树变大时,这样做效率非常低且不实用。我还可以使用较新的 elementFromPoint 从查询元素中采样位置,以确保它确实在顶部,但这似乎效率很低。

关于如何更好地做到这一点的任何想法?

谢谢!

4

2 回答 2

2

我想不出比使用 elementFromPoint 更简单的方法。您似乎不想使用它,但可以给您一些一致的结果。如果有多层元素,您应该调整代码以移动已经抓取的元素或将它们设置为不可见并调用函数以获取新的数据元素集。

对于基本思想:

function upperElements(el) {
    var top = el.offsetTop,
        left = el.offsetLeft,
        width = el.offsetWidth,
        height = el.offsetHeight,
        elemTL = document.elementFromPoint(left, top),
        elemTR = document.elementFromPoint(left + width - 1, top),
        elemBL = document.elementFromPoint(left, top + height - 1),
        elemBR = document.elementFromPoint(left + width - 1, top + height - 1),
        elemCENTER = document.elementFromPoint(parseInt(left + (width / 2)), parseInt(top + (height / 2))),
        elemsUpper = [];
    if (elemTL != el) elemsUpper.push(elemTL);
    if (elemTR != el && $.inArray(elemTR, elemsUpper) === -1) elemsUpper.push(elemTR);
    if (elemBL != el && $.inArray(elemBL, elemsUpper) === -1) elemsUpper.push(elemBL);
    if (elemBR != el && $.inArray(elemBR, elemsUpper) === -1) elemsUpper.push(elemBR);
    if (elemCENTER != el && $.inArray(elemCENTER, elemsUpper) === -1) elemsUpper.push(elemCENTER);
    return elemsUpper;
}​

jsFiddle

于 2012-11-01T20:48:22.517 回答
0

不幸的是,没有办法不遍历所有 DOM 元素的解决方案,因为您可以通过 CSS 规则将任何元素放在屏幕上的任何位置。

你可以做到的最好的实际上是迭代所有 DOM 元素以进行命中测试。

如果我必须这样做,我会依赖 jQuery,它是一个广泛使用的跨浏览器 API,并且在不断改进。

看看http://api.jquery.com/position/http://api.jquery.com/width/http://api.jquery.com/height/

如果性能非常重要,您可以通过深入研究它们的实现并针对您的特定情况改进它来获得一个因素,但请记住,复杂性不会低于 O(DOM 元素数)

于 2012-11-01T19:56:20.897 回答