Klicken Sie sich durch div zu den zugrunde liegenden Elementen


1592

Ich habe eine div, die background:transparentzusammen mit hat border. Darunter habe divich mehr Elemente.

Derzeit kann ich auf die zugrunde liegenden Elemente klicken, wenn ich außerhalb des Overlays klicke div. Ich kann jedoch nicht auf die zugrunde liegenden Elemente klicken, wenn ich direkt auf das Overlay klicke div.

Ich möchte in der Lage sein, dies divdurchzuklicken, damit ich auf die zugrunde liegenden Elemente klicken kann.

Mein Problem

Antworten:


2614

Ja, man KANN dies tun.

Wenn Sie pointer-events: noneCSS-bedingte Anweisungen für IE11 verwenden (funktioniert nicht in IE10 oder niedriger), können Sie eine browserübergreifende Lösung für dieses Problem erhalten.

Mit AlphaImageLoaderkönnen Sie sogar transparente .PNG/.GIFs in das Overlay einfügen divund Klicks zu darunter liegenden Elementen fließen lassen.

CSS:

pointer-events: none;
background: url('your_transparent.png');

IE11 bedingt:

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='your_transparent.png', sizingMethod='scale');
background: none !important;

Hier ist eine grundlegende Beispielseite mit dem gesamten Code.


7
Was ist, wenn ich Übergänge oder Schwebezustände auf diesem Div verwende?
Mantikor

2
@Manticore Kurze Antwort: Sie können nicht. In diesem Fall funktioniert die angegebene Antwort nicht.
Niels Abildgaard

10
IE11 unterstützt Zeigerereignisse vollständig. Dies bedeutet, dass alle modernen Browser dies unterstützen. Dies ist eine praktikable Lösung ab Ende 2014. caniuse.com/#search=pointer-events
Judah Gabriel Himango

Wie von @Andy festgestellt, wird das Scrollen unterbrochen. Ich habe ein separates Problem geöffnet, um zu prüfen,
Oliver Joseph Ash

1
@Manticore Ich habe festgestellt, dass Sie "Zeigerereignisse: keine;" überschreiben können. für verschachtelte Elemente, so dass Sie etwas schreiben können, das durch Klicken umgangen wird, mit etwas, das den Klick und darüber bringt, für die überschriebenen Teile können Sie Effekte verwenden und klicken
Luca C.

292

Auch schön zu wissen ...
Sie können Zeigerereignisse in einem übergeordneten Element (wahrscheinlich transparentes div) deaktivieren, es aber weiterhin für seine untergeordneten Elemente aktivieren.
Dies ist hilfreich, wenn Sie mit mehreren überlappenden Div-Ebenen arbeiten, in denen Sie auf untergeordnete Elemente klicken möchten, während die übergeordneten Ebenen überhaupt nicht auf Mausereignisse reagieren.

Dafür erhalten alle Eltern-Divs pointer-events: noneund ihre anklickbaren Kinder Zeiger-Ereignisse, die von wieder aktiviert werdenpointer-events: auto

.parent {
    pointer-events:none;        
}
.child {
    pointer-events:auto;
}

<div class="some-container">
   <ul class="layer-0 parent">
     <li class="click-me child"></li>
     <li class="click-me child"></li>
   </ul>

   <ul class="layer-1 parent">
     <li class="click-me-also child"></li>
     <li class="click-me-also child"></li>
   </ul>
</div>

4
Perfekt, das ist genau das, was ich brauchte!
RobbyReindeer

1
super hilfreich, danke
SpaceBear

43

Das Zulassen, dass der Benutzer durch a divauf das zugrunde liegende Element klickt, hängt vom Browser ab. Alle modernen Browser, einschließlich Firefox, Chrome, Safari und Opera, verstehen pointer-events:none.

Für IE hängt es vom Hintergrund ab. Wenn der Hintergrund transparent ist, funktioniert das Durchklicken, ohne dass Sie etwas tun müssen. Auf der anderen Seite background:white; opacity:0; filter:Alpha(opacity=0);benötigt der IE für so etwas wie eine manuelle Ereignisweiterleitung.

Siehe einen JSFiddle-Test und CanIUse-Zeigerereignisse .


20

Ich füge diese Antwort hinzu, weil ich sie hier nicht vollständig gesehen habe. Ich konnte dies mit elementFromPoint tun. Also im Grunde genommen:

  • Fügen Sie dem Div, durch das Sie geklickt werden möchten, einen Klick hinzu
  • Verstecke es
  • Bestimmen Sie, auf welchem ​​Element sich der Zeiger befindet
  • Feuern Sie den Klick auf das Element dort.
var range-selector= $("")
    .css("position", "absolute").addClass("range-selector")
    .appendTo("")
    .click(function(e) {
        _range-selector.hide();

        $(document.elementFromPoint(e.clientX,e.clientY)).trigger("click");
    });

In meinem Fall ist das überlagerte Div absolut positioniert - ich bin mir nicht sicher, ob dies einen Unterschied macht. Dies funktioniert zumindest unter IE8 / 9, Safari Chrome und Firefox.


12
  1. Überlagern Sie das Element
  2. Bestimmen Sie die Cursorkoordinaten
  3. Holen Sie sich ein Element auf diese Koordinaten
  4. Triggerklick auf Element
  5. Überlagerndes Element erneut anzeigen
$('#elementontop').click(e => {
    $('#elementontop').hide();
    $(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
    $('#elementontop').show();
});

Haben Sie vergessen, die Apostrophe zu schließen? Vielleicht $('#elementontop)sollte es sein $('#elementontop')?
Johannchopin

10

Ich musste dies tun und entschied mich für diesen Weg:

$('.overlay').click(function(e){
    var left = $(window).scrollLeft();
    var top = $(window).scrollTop();

    //hide the overlay for now so the document can find the underlying elements
    $(this).css('display','none');
    //use the current scroll position to deduct from the click position
    $(document.elementFromPoint(e.pageX-left, e.pageY-top)).click();
    //show the overlay again
    $(this).css('display','block');
});

6

Ich arbeite derzeit mit Sprechblasen auf Leinwand. Da der Ballon mit dem Zeiger jedoch in ein Div eingeschlossen ist, können einige Links darunter nicht mehr angeklickt werden. Ich kann in diesem Fall keine extjs verwenden. Siehe grundlegendes Beispiel für mein Sprachballon-Tutorial erfordert HTML5

Also habe ich beschlossen, alle Verbindungskoordinaten aus den Ballons in einem Array zu sammeln.

var clickarray=[];
function getcoo(thatdiv){
         thatdiv.find(".link").each(function(){
                 var offset=$(this).offset();           
                 clickarray.unshift([(offset.left),
                                     (offset.top),
                                     (offset.left+$(this).width()),
                                     (offset.top+$(this).height()),
                                     ($(this).attr('name')),
                                     1]);
                                     });
         }

Ich rufe diese Funktion bei jedem (neuen) Ballon auf. Es erfasst die Koordinaten der linken / oberen und rechten / unteren Ecke einer link.class - zusätzlich das Namensattribut für das, was zu tun ist, wenn jemand auf diese Koordinaten klickt und ich gerne eine 1 setze, was bedeutet, dass es kein angeklickter Jet ist . Verschieben Sie dieses Array in das Clickarray. Sie könnten auch Push verwenden.

So arbeiten Sie mit diesem Array:

$("body").click(function(event){
          event.preventDefault();//if it is a a-tag
          var x=event.pageX;
          var y=event.pageY;
          var job="";
          for(var i in clickarray){
              if(x>=clickarray[i][0] && x<=clickarray[i][2] && y>=clickarray[i][1] && y<=clickarray[i][3] && clickarray[i][5]==1){
                 job=clickarray[i][4];
                 clickarray[i][5]=0;//set to allready clicked
                 break;
                }
             }
          if(job.length>0){   
             // --do some thing with the job --
            }
          });

Diese Funktion prüft die Koordinaten eines Body-Click-Ereignisses oder ob es bereits angeklickt wurde, und gibt das Namensattribut zurück. Ich denke, es ist nicht notwendig, tiefer zu gehen, aber Sie sehen, es ist nicht so kompliziert. Die Hoffnung war großartig ...


4

es funktioniert nicht so. Die Problemumgehung besteht darin, die Koordinaten des Mausklicks manuell mit dem Bereich zu vergleichen, den jedes Element einnimmt.

Der Bereich, der von einem Element belegt wird, kann gefunden werden, indem 1. die Position des Elements in Bezug auf oben links auf der Seite ermittelt wird und 2. die Breite und Höhe. Eine Bibliothek wie jQuery macht dies ziemlich einfach, obwohl dies in einfachen js möglich ist. Durch Hinzufügen eines Ereignishandlers für mousemovedas documentObjekt werden die Mauspositionen oben und links auf der Seite kontinuierlich aktualisiert. Die Entscheidung, ob sich die Maus über einem bestimmten Objekt befindet, besteht darin, zu überprüfen, ob sich die Mausposition zwischen dem linken, rechten, oberen und unteren Rand eines Elements befindet.


2
Wie oben erwähnt, können Sie dies mit CSSs {pointer-events: none;} auf Ihrem transparenten Container erreichen.
Empereol

4

Nein, Sie können nicht durch ein Element klicken. Sie können die Koordinaten des Klicks abrufen und versuchen, herauszufinden, welches Element sich unter dem angeklickten Element befand. Dies ist jedoch für Browser ohne Klick sehr mühsam document.elementFromPoint. Dann müssen Sie immer noch die Standardaktion des Klickens emulieren, was nicht unbedingt trivial ist, je nachdem, welche Elemente Sie dort haben.

Da Sie einen vollständig transparenten Fensterbereich haben, ist es wahrscheinlich besser, ihn als separate Randelemente an der Außenseite zu implementieren, sodass der mittlere Bereich frei von Hindernissen bleibt und Sie einfach direkt durchklicken können.


4

Eine andere Idee (situativ) zu versuchen wäre:

  1. Fügen Sie den gewünschten Inhalt in ein div ein.
  2. Legen Sie die nicht klickende Überlagerung über die gesamte Seite mit einem höheren Z-Index.
  3. Machen Sie eine weitere beschnittene Kopie des Original-Div
  4. Overlay und Abs positionieren die Kopie div an der gleichen Stelle wie der ursprüngliche Inhalt, auf den Sie mit einem noch höheren Z-Index klicken möchten.

Irgendwelche Gedanken?


2

Ich denke, dass Sie erwägen können, Ihr Markup zu ändern. Wenn ich mich nicht irre, möchten Sie eine unsichtbare Ebene über dem Dokument platzieren, und Ihr unsichtbares Markup steht möglicherweise vor Ihrem Dokumentbild (ist das richtig?).

Stattdessen schlage ich vor, dass Sie das Unsichtbare direkt nach dem Dokumentbild platzieren, aber die Position in absolut ändern.

Beachten Sie, dass Sie ein übergeordnetes Element benötigen, um position: relative zu haben, und dann können Sie diese Idee verwenden. Andernfalls wird Ihre absolute Ebene genau in der oberen linken Ecke platziert.

Ein absolutes Positionselement wird relativ zum ersten übergeordneten Element positioniert, das eine andere Position als statisch hat. Wenn kein solches Element gefunden wird, ist der enthaltende Block HTML

Hoffe das hilft. Sehen Sie hier für weitere Informationen über CSS - Positionierung.


2

Wickeln Sie azum Beispiel einfach ein Tag um den gesamten HTML-Extrakt

<a href="/categories/1">
  <img alt="test1" class="img-responsive" src="/assets/photo.jpg" />
  <div class="caption bg-orange">
    <h2>
      test1
    </h2>
  </div>
</a>

In meinem Beispiel hat meine Beschriftungsklasse Hover-Effekte, die bei Zeigerereignissen auftreten: keine; du wirst einfach verlieren

Wenn Sie den Inhalt einpacken, bleiben Ihre Hover-Effekte erhalten, und Sie können auf das gesamte Bild klicken, einschließlich Div, Grüße!


guter Punkt! Danke
Mr.Vertigo

1

Sie können ein AP-Overlay wie ...

#overlay {
  position: absolute;
  top: -79px;
  left: -60px;
  height: 80px;
  width: 380px;
  z-index: 2;
  background: url(fake.gif);
}
<div id="overlay"></div>

Legen Sie es einfach dort hin, wo Sie es nicht wollen, dh klicken Sie darauf. Funktioniert in allen.


1

Eine einfachere Möglichkeit wäre, das transparente Hintergrundbild mithilfe von Daten-URIs wie folgt zu integrieren:

.click-through {
    pointer-events: none;
    background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
}

0

Ich denke, das event.stopPropagation();sollte auch hier erwähnt werden. Fügen Sie dies der Klickfunktion Ihrer Schaltfläche hinzu.

Verhindert, dass das Ereignis in den DOM-Baum sprudelt, und verhindert, dass übergeordnete Handler über das Ereignis benachrichtigt werden.


0

Dies ist keine genaue Antwort auf die Frage, kann jedoch bei der Suche nach einer Problemumgehung hilfreich sein.

Ich hatte ein Bild, das ich beim Laden der Seite versteckte und beim Warten auf einen AJAX-Anruf anzeigte und dann jedoch wieder versteckte ...

Ich habe die einzige Möglichkeit gefunden, mein Bild beim Laden der Seite anzuzeigen und es dann verschwinden zu lassen und in der Lage zu sein, auf Dinge zu klicken, an denen sich das Bild befand, bevor es ausgeblendet wurde, um das Bild in einen DIV zu legen, die Größe des DIV auf 10 x 10 Pixel oder klein zu machen genug, um zu verhindern, dass es ein Problem verursacht, und dann das enthaltende div auszublenden. Dies ermöglichte es dem Bild, das Div zu überlaufen, während es sichtbar war, und wenn das Div ausgeblendet war, war nur der Div-Bereich von der Unfähigkeit betroffen, auf Objekte darunter zu klicken, und nicht von der gesamten Größe des Bildes, das der DIV enthielt und anzeigte.

Ich habe alle Methoden ausprobiert, um das Bild auszublenden, einschließlich CSS-Anzeige = keine / Block, Deckkraft = 0, wobei das Bild mit hidden = true ausgeblendet wurde. Alle führten dazu, dass mein Bild ausgeblendet wurde, aber der Bereich, in dem es angezeigt wurde, um sich so zu verhalten, als wäre das darunter liegende Material abgedeckt, sodass Klicks usw. nicht auf die zugrunde liegenden Objekte einwirken würden. Sobald sich das Bild in einem winzigen DIV befand und ich den winzigen DIV versteckte, war der gesamte vom Bild eingenommene Bereich klar und nur der winzige Bereich unter dem von mir versteckten DIV war betroffen, aber als ich ihn klein genug machte (10 x 10 Pixel), war das Problem wurde behoben (irgendwie).

Ich fand, dass dies eine schmutzige Problemumgehung für ein einfaches Problem ist, aber ich konnte keine Möglichkeit finden, das Objekt in seinem nativen Format ohne Container auszublenden. Mein Objekt war in Form von usw. Wenn jemand einen besseren Weg hat, lassen Sie es mich bitte wissen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.