Das Problem:
Das eigentliche Problem ist, dass es so viele Möglichkeiten, dass ein Element abgedeckt werden kann. Zum Beispiel, ist das Element mit 4 anderen Elementen bedeckt und nur ein Raum ist in der Mitte offen? Beispiel dafür, was ich meine:
das rote Feld Unter der Annahme, ist das Element in Frage, die kleine Box direkt in der Mitte ist eine direkte Sicht des Element.
Aufgrund dieser Probleme kann es sehr "teuer" werden, festzustellen, ob das Element über einen Bereich verfügt, der erhöht werden kann.
Die Lösung:
Ich kam mit einer Lösung oben mit boundingClientRect
, document.elementFromPoint
und Dokumenten-Scrollen. Er versucht, schnell zu bestimmen, indem er die 4 Ecken des fraglichen Elements überprüft und dann, wenn diese falsch zurückkommen, beginnt, das gesamte Element mit einer bestimmten "Genauigkeit" zu prüfen.
UPDATE:
ich in einer Art und Weise hinzugefügt haben Elemente zu überprüfen, die nicht einmal in der Ansicht sind. Dies geschieht, indem versucht wird, das Element zu durchlaufen, die Prüfung auszuführen und dann zurück zur vorherigen Position zu scrollen, bevor die Prüfung gestartet wurde. Dies geschieht so schnell, dass keine sichtbaren Sprünge auftreten.
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 (Beispiel Elemente aktualisiert wurde, um die Seite nach unten gescrollt zu reflektieren), komplett mit ein paar Tests. Sie müssen die Browserkonsole öffnen, um die Testergebnisse anzuzeigen. Wahrscheinlich möchten Sie dies auch zuerst in Chrome oder Firefox testen, da ich dies nicht selbst getestet habe.
Ein paar Dinge zu erinnern:
Wenn die 4-Ecke Prüfung fehlschlägt, dann wird es teuer, den Rest des Elements zu überprüfen. Je kleiner die "Genauigkeit", desto teurer wird es. Diese Nummer bestimmt, wie oft der Check ausgeführt wird. Also, wenn die Genauigkeit 1
ist, dann wird es jeden 1px überprüfen. Wenn die Nummer 10
ist, überprüft es alle 10px auf der X- und Y-Achse.
Es sollte beachtet werden, dass es fast keine Möglichkeit gibt, die Variationen von Elementen auf der Seite zu kennen. Sie erwähnen in einem Kommentar, dass einige Elemente verschwinden können, die während der Überprüfung "blockiert" wurden, aber nicht, während ein Benutzer interagiert.Es gibt keine Möglichkeit, diese Funktionalität kurz vor AI zu kennen. Diese Funktion soll jedoch nach Ihrer Wahl aufgerufen werden, nicht nur beim Laden der Seite.
Ich glaube nicht, dass dies möglich ist, weil jedes Element über schwebte. Elemente haben kein Wissen über ihre Beziehung zueinander, so dass Sie sie nicht fragen können. –
@AniketSahrawat ja, aber das würde OPs Frage zu transparenten Elementen nicht beantworten. –
@charlieg Manchmal können Sie etwas mit document.elementFromPoint (x, y) tun, aber ich möchte etwas vollständiger – JaneCC