Я использую API document.elementFromPoint
для получения элемента, находящегося в точке. Но я не хочу иметь все элементы - некоторые из них не квалифицированы, например, inline
элементов. Поэтому я делаю неквалифицированные элементы временно невидимыми, чтобы захватить элемент, который находится под ним.Временно сделать элемент невидимым
Отмеченный код.
import { elementQualified, elementFromPoint } from './utils';
function makeInvisible(element) {
let oldVisibility = element.style.visibility;
/* this is supposed to make the element invisible immediately, without
* any delay. When a `transition` property is set which includes the
* `visibility` property, this is sometimes unfortunately not the case. */
element.style.visibility = "hidden";
/* this is the undo function being called at the end. */
return() => {
element.style.visibility = oldVisibility;
};
}
export default function(x, y) {
var undo = [], element, last;
/* in a loop, we grab the top-most element that is at a certain coordinate
* inside the viewport. The `last` variable is preventing an infinite loop
* in cases, where `makeInvisible()` does not work. */
while (((element = elementFromPoint(x, y)) !== null) && (last !== element)) {
/*
* In order to be qualified, this element including its ancestors must
* all be qualified. For instance, if this is a block element but the
* parent for some reason is an inline element, this is not desired. */
if (withAncestors(element).every(elementQualified)) {
break;
}
/* if the element is not qualified, we make it invisible and add it to the
* start of the `undo` array which is being batch-called after this loop. */
undo.unshift(makeInvisible(element));
/* and the loop protection */
last = element;
}
/* undo all changes */
undo.forEach((fn) => fn());
/* check if we broke the loop or we have selected the topmost element
* in which case we discard the result. */
if ((last === element) || (element === document.documentElement)) {
return null;
}
return element;
}
Если элемент, который должен стать невидимыми имеет набор transition
свойства, которое включает в себя visibility
свойства, оно не станет невидимым сразу. Возьмем, например, transition: all 0.3s ease-in-out
. После установки element.style.visibility
на hidden
это займет 0.3s
, после чего элемент фактически невидим и document.elementFromPoint
выберет элемент под ним. В результате цикл прерывается, потому что document.elementFromPoint
возвращает два раза идентичный элемент.
Я не собираюсь временно устанавливать свойство display
, потому что он вызывает изменения компоновки, и я создаю инструмент, для которого изменения макета не работают.
Cant удалить переход перед установкой элемента к невидимому и установить его обратно, как только вы сделано? – Lain
«_ ... отображение свойства ... вызывает изменения макета». Это не так, когда вы выполняете всю обработку DOM синхронно и устанавливаете все, как было, прежде чем дать браузеру возможность отобразить страницу. Следовательно, установка 'display: none' в скрипте не будет отображаться на странице, если вы удалите стиль до окончания скрипта. – Teemu
Я уже пробовал опцию 'display: none'. Это вызывает некоторые изменения макета и проблемы прокрутки для меня. – Vincent