Получить элемент из точки, когда у вас есть перекрывающиеся элементы?

Вы можете использовать это, чтобы найти элемент документа в заданной точке

document.elementFromPoint(x, y);

Что вы можете сделать, если в точке есть перекрывающиеся элементы? (Я знаю, что это не отличный способ сделать что-то - попытку хакерского обходного пути для ошибки до крайнего срока).

Ответы

Ответ 1

Как я думаю, вы уже знаете, document.elementFromPoint(x, y); возвращает только самый верхний элемент, который перекрывает эту точку.

Если то, что вы пытаетесь сделать, это найти все элементы, которые накладываются на заданную точку, даже элементы за другими элементами, тогда я не знаю о какой-либо функции DOM, которая сделает это за вас. Возможно, вам придется писать свои собственные.

Несколько хакерской версией было бы вызвать elementFromPoint(x,y), помнить этот элемент DOM, затем скрыть этот элемент с display: none, а затем вызвать elementFromPoint(x,y) снова, пока все, что вы получите, не является телом, а затем восстановите элементы вы спрятались.

Менее хакерской версией будет цикл, хотя все объекты на странице, и сравните их смещение/высоту/ширину на странице с вашей точкой.

Вот один из способов сделать это:

function getAllElementsFromPoint(x, y) {
    var elements = [];
    var display = [];
    var item = document.elementFromPoint(x, y);
    while (item && item !== document.body && item !== window && item !== document && item !== document.documentElement) {
        elements.push(item);
        display.push(item.style.display);
        item.style.display = "none";
        item = document.elementFromPoint(x, y);
    }
    // restore display property
    for (var i = 0; i < elements.length; i++) {
        elements[i].style.display = display[i];
    }
    return elements;
}

Рабочая демонстрация: http://jsfiddle.net/jfriend00/N9pu9/

Ответ 2

Если вы хотите найти все элементы DOM, которые перекрывают точку, вы можете просто использовать document.elementsFromPoint(), который возвращает массив всех элементов, найденных в указанной точке (очевидно, упорядоченный сверху вниз относительно области просмотра, т.е.: если есть оверлей, он будет отображаться первым в массиве)

Ответ 3

Не уверен, по какой причине был задан начальный вопрос, но если вам нужно обнаружить элемент, который в настоящее время перетаскивается с помощью элемента touch или mouse, вы можете установить pointer-events: none; на перетаскиваемом элементе. Когда вы это сделаете, document.elementFromPoint() будет игнорировать текущий перетаскиваемый элемент и вернуть его под ним.

Ответ 4

Простое решение

В случае, когда $e является перекрывающимся элементом, e является событием

$e.style.display = 'none';
var b = document.elementFromPoint(e.clientX,e.clientY);
$e.style.display = 'block';

Ответ 5

Итак, насколько я вижу, этот ответ - fooobar.com/info/8180598/... - был бы идеальным, но, к сожалению, document.elementsFromPoint() не работает в IE11.

В противном случае код в этом ответе - fooobar.com/info/8180598/... кажется, работает в большинстве современных браузеров, включая IE11, но есть ошибка, при которой определенные элементы DOM дублируются в массиве, возвращаемом функцией,

Однако, если кто-то ищет shim document.elementsFromPoint(), хороший пример можно найти здесь:

https://gist.github.com/oslego/7265412

Скопировано здесь для удобства:

function elementsFromPoint(x,y) {
    var elements = [], previousPointerEvents = [], current, i, d;

        // get all elements via elementFromPoint, and remove them from hit-testing in order
    while ((current = document.elementFromPoint(x,y)) && elements.indexOf(current)===-1 && current != null) {

            // push the element and its current style
        elements.push(current);
        previousPointerEvents.push({
                value: current.style.getPropertyValue('pointer-events'),
                priority: current.style.getPropertyPriority('pointer-events')
            });

            // add "pointer-events: none", to get to the underlying element
        current.style.setProperty('pointer-events', 'none', 'important'); 
    }

        // restore the previous pointer-events values
    for(i = previousPointerEvents.length; d=previousPointerEvents[--i]; ) {
        elements[i].style.setProperty('pointer-events', d.value?d.value:'', d.priority); 
    }

        // return our results
    return elements;
}