2016-11-29 2 views
2

Mit einem Bookmarklet möchte ich ein img-Element mit einem Handler für mouseenter- und mouseleave-Ereignisse mit jquery .hover() binden, aber in einigen Fällen werden die Mausereignisse niemals ausgeführt ausgelöst werden, weil das img-Element irgendwie von der Maus versteckt ist, obwohl das Bild tatsächlich sichtbar ist: Ein einfaches Beispiel ist, wenn es von einem transparenten Element überlappt wird. Wenn Sie mit einem Tool wie dem Firefigh Inspector spielen, werden Sie viele Beispiele finden.Programmatisch erkennen, ob ein Element schweben kann oder nicht

Wie kann ich diese Art von Verhalten herausfinden? Im Idealfall möchte ich eine Funktion erstellen, die je nachdem, ob das Element erweiterbar ist oder nicht, einen Wert true oder false zurückgibt.

Vielen Dank an all

+0

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. –

+0

@AniketSahrawat ja, aber das würde OPs Frage zu transparenten Elementen nicht beantworten. –

+1

@charlieg Manchmal können Sie etwas mit document.elementFromPoint (x, y) tun, aber ich möchte etwas vollständiger – JaneCC

Antwort

5

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:

enter image description here

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.

+0

Das ist interessant, weil das genau eine Lösung ist, die ich versuchte, bevor Sie diese Frage stellen (siehe https://stackoverflow.com/a/ 40877241/7221380) es ist nicht schlecht, aber es gibt einige Nachteile: – JaneCC

+0

1) Dies funktioniert nur, wenn Element innerhalb des Ansichtsfensters ist, also wenn Sie nicht angemessen das Fenster durch Javascript für jedes Element scrollen, wird dies nicht für alle Elemente funktionieren. 2) Ich habe eine Situation gesehen, in der element1 von element2 abgedeckt wird und wenn Sie element2 schweben, dann kommt element1 an oberster Stelle, und dann ist element1 behebbar. Ich bin mir bewusst, dass dies eine Art extremer Situation ist, aber vielleicht gibt es andere, die ich nicht im Sinn habe (eine Liste solcher Situationen zu erstellen ist willkommen). – JaneCC

+0

Nun, wenn keine bessere Lösung Oberfläche in den kommenden Tagen werde ich Ihre Antwort akzeptieren, die in der Nähe der besten sein könnte, die man in dieser Angelegenheit erreichen kann. Danke für die Bemühung. – JaneCC

Verwandte Themen