Wie kann ich feststellen, ob ein DOM-Element im aktuellen Ansichtsfenster sichtbar ist?
949
Gibt es eine effiziente Methode, um festzustellen, ob ein DOM-Element (in einem HTML-Dokument) derzeit sichtbar ist (im Ansichtsfenster angezeigt wird )?
Kommt darauf an, was du mit sichtbar meinst. Wenn Sie meinen, dass es derzeit auf der Seite angezeigt wird, können Sie es anhand der Bildlaufposition basierend auf den Elementen y-Versatz und der aktuellen Bildlaufposition berechnen.
Roryf
18
Erläuterung: Sichtbar wie im aktuell angezeigten Rechteck. Sichtbar, wie in nicht versteckt oder Anzeige: keine? Sichtbar, wie nicht hinter etwas anderem in der Z-Reihenfolge?
Adam Wright
6
wie innerhalb des aktuell angezeigten Rechtecks. Vielen Dank. Umformuliert.
Benzaita
2
Beachten Sie, dass alle Antworten hier ein falsches Positiv für Elemente ergeben, die sich außerhalb des sichtbaren Bereichs ihres übergeordneten Elements befinden (z. B. mit ausgeblendetem Überlauf), aber innerhalb des Ansichtsfensterbereichs.
Update: Die Zeit vergeht und unsere Browser auch. Diese Technik wird nicht mehr empfohlen und Sie sollten Dans Lösung verwenden, wenn Sie die Version von Internet Explorer nicht vor 7 unterstützen müssen.
Ursprüngliche Lösung (jetzt veraltet):
Dadurch wird überprüft, ob das Element im aktuellen Ansichtsfenster vollständig sichtbar ist:
function elementInViewport(el){var top = el.offsetTop;var left = el.offsetLeft;var width = el.offsetWidth;var height = el.offsetHeight;while(el.offsetParent){
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;}return(
top >= window.pageYOffset &&
left >= window.pageXOffset &&(top + height)<=(window.pageYOffset + window.innerHeight)&&(left + width)<=(window.pageXOffset + window.innerWidth));}
Sie können dies einfach ändern, um festzustellen, ob ein Teil des Elements im Ansichtsfenster sichtbar ist:
function elementInViewport2(el){var top = el.offsetTop;var left = el.offsetLeft;var width = el.offsetWidth;var height = el.offsetHeight;while(el.offsetParent){
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;}return(
top <(window.pageYOffset + window.innerHeight)&&
left <(window.pageXOffset + window.innerWidth)&&(top + height)> window.pageYOffset &&(left + width)> window.pageXOffset);}
Was ist, wenn das Element in einem scrollbaren Div lebt und aus einer Ansicht gescrollt wird?
Amartynov
2
Bitte überprüfen Sie eine neuere Version des Skripts unten
Dan
1
Auch neugierig auf @ amartynovs Frage. Weiß jemand, wie man einfach erkennt, ob ein Element aufgrund eines Überlaufs eines Vorfahrenelements ausgeblendet ist? Bonus, wenn dies unabhängig davon erkannt werden kann, wie tief das Kind verschachtelt ist.
Eric Nguyen
1
@deadManN, das durch das DOM rekursiert, ist notorisch langsam. Grund genug, aber die Browser-Anbieter haben auch getBoundingClientRectspeziell für die Suche nach Elementkoordinaten erstellt ... Warum sollten wir sie nicht verwenden?
Diese Lösung wurde auf Internet Explorer 7 (und höher), iOS 5 (und höher) Safari, Android 2.0 (Eclair) und höher, BlackBerry, Opera Mobile und Internet Explorer Mobile 9 getestet .
function isElementInViewport (el){// Special bonus for those using jQueryif(typeof jQuery ==="function"&& el instanceof jQuery){
el = el[0];}var rect = el.getBoundingClientRect();return(
rect.top >=0&&
rect.left >=0&&
rect.bottom <=(window.innerHeight || document.documentElement.clientHeight)&&/* or $(window).height() */
rect.right <=(window.innerWidth || document.documentElement.clientWidth)/* or $(window).width() */);}
Wie benutzt man:
Sie können sicher sein, dass die oben angegebene Funktion zum Zeitpunkt des Aufrufs die richtige Antwort zurückgibt. Wie steht es jedoch mit der Sichtbarkeit des Elements als Ereignis?
Platzieren Sie den folgenden Code am unteren Rand Ihres <body>Tags:
function onVisibilityChange(el, callback){var old_visible;returnfunction(){var visible = isElementInViewport(el);if(visible != old_visible){
old_visible = visible;if(typeof callback =='function'){
callback();}}}}var handler = onVisibilityChange(el,function(){/* Your code go here */});// jQuery
$(window).on('DOMContentLoaded load resize scroll', handler);/* // Non-jQuery
if (window.addEventListener) {
addEventListener('DOMContentLoaded', handler, false);
addEventListener('load', handler, false);
addEventListener('scroll', handler, false);
addEventListener('resize', handler, false);
} else if (window.attachEvent) {
attachEvent('onDOMContentLoaded', handler); // Internet Explorer 9+ :(
attachEvent('onload', handler);
attachEvent('onscroll', handler);
attachEvent('onresize', handler);
}
*/
Wenn Sie DOM-Änderungen vornehmen, können diese natürlich die Sichtbarkeit Ihres Elements ändern.
Richtlinien und häufige Fallstricke:
Möglicherweise müssen Sie den Seitenzoom / die Prise des Mobilgeräts verfolgen? jQuery sollte den Cross-Browser Zoom / Pinch verarbeiten , andernfalls sollte der erste oder zweite Link Ihnen helfen.
Wenn Sie das DOM ändern , kann dies die Sichtbarkeit des Elements beeinträchtigen. Sie sollten die Kontrolle darüber übernehmen und handler()manuell anrufen . Leider haben wir kein browserübergreifendes onrepaintEreignis. Auf der anderen Seite können wir Optimierungen vornehmen und nur DOM-Änderungen überprüfen, die die Sichtbarkeit eines Elements ändern können.
Verwenden Sie es niemals nur in jQuery $ (document) .ready () , da in diesem Moment keine Garantie für CSS besteht . Ihr Code kann lokal mit Ihrem CSS auf einer Festplatte arbeiten, aber sobald er auf einem Remote-Server installiert ist, schlägt er fehl.
Wir können das Zoom / Pinch-Ereignis noch nicht erfassen.
Der letzte Ausweg könnte der folgende Code sein:
/* TODO: this looks like a very bad code */
setInterval(handler,600);
Sie können die fantastische Funktion pageVisibiliy der HTML5-API verwenden, wenn Sie sich dafür interessieren, ob die Registerkarte mit Ihrer Webseite aktiv und sichtbar ist.
TODO: Diese Methode behandelt nicht zwei Situationen:
Überlappung mit z-index
Verwenden overflow-scrollim Container des Elements
Ich verwende diese Lösung (Vorsicht vor dem Tippfehler "botom"). Es gibt auch etwas zu beachten, wenn das Element, das wir betrachten, Bilder enthalten würde. Chrome muss (zumindest) warten, bis das Bild geladen ist, damit es den genauen Wert für das BoundingRectangle hat. Scheint, dass Firefox dieses "Problem" nicht hat
Claudio
4
Funktioniert es, wenn Sie das Scrollen in einem Container innerhalb des Körpers aktiviert haben? Zum Beispiel funktioniert es hier nicht - agaase.github.io/webpages/demo/isonscreen2.html isElementInViewport (document.getElementById ("innerele")). Innerele befindet sich in einem Container, in dem das Scrollen aktiviert ist.
Agaase
70
Die Berechnungen gehen davon aus, dass das Element kleiner als der Bildschirm ist. Wenn Sie hohe oder breite Elemente haben, ist es möglicherweise genauer zu verwendenreturn (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
Roonaan
11
Tipp: Für diejenigen, die versuchen, dies mit jQuery zu implementieren, nur eine freundliche Erinnerung, das HTML-DOM-Objekt (z. B. isElementInViewport(document.getElementById('elem'))) und nicht das jQuery-Objekt (z isElementInViewport($("#elem)). B. ) zu übergeben. Das jQuery-Äquivalent lautet [0]wie folgt : isElementInViewport($("#elem)[0]).
Bessere Leistung als das Abhören von Bildlaufereignissen
Funktioniert in domänenübergreifenden Iframes
Kann erkennen, ob ein Element ein anderes blockiert / schneidet
Intersection Observer ist auf dem Weg zu einem vollwertigen Standard und wird bereits in Chrome 51+, Edge 15+ und Firefox 55+ unterstützt und befindet sich in der Entwicklung für Safari. Es gibt auch eine Polyfüllung .
Vorherige Antwort
Es gibt einige Probleme mit der Antwort von Dan , die es für einige Situationen zu einem ungeeigneten Ansatz machen könnten. Einige dieser Probleme werden in seiner Antwort am unteren Rand darauf hingewiesen, dass sein Code falsch positive Ergebnisse für Elemente liefert, die:
Versteckt durch ein anderes Element vor dem zu testenden
Außerhalb des sichtbaren Bereichs eines übergeordneten oder Vorfahrenelements
Ein Element oder seine untergeordneten Elemente, die mithilfe der CSS- clipEigenschaft ausgeblendet wurden
Hier finden Sie eine Lösung für diese Probleme mit dem folgenden Testergebnis und einer Erläuterung einiger Teile des Codes.
function isElementVisible(el){var rect = el.getBoundingClientRect(),
vWidth = window.innerWidth || document.documentElement.clientWidth,
vHeight = window.innerHeight || document.documentElement.clientHeight,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right <0|| rect.bottom <0|| rect.left > vWidth || rect.top > vHeight)returnfalse;// Return true if any of its four corners are visiblereturn(
el.contains(efp(rect.left, rect.top))|| el.contains(efp(rect.right, rect.top))|| el.contains(efp(rect.right, rect.bottom))|| el.contains(efp(rect.left, rect.bottom)));}
Diese Methode ist jedoch nicht ohne Einschränkungen. Zum Beispiel würde ein Element, das mit einem niedrigeren Z-Index als ein anderes Element an derselben Stelle getestet wird, als versteckt identifiziert, selbst wenn das vordere Element tatsächlich keinen Teil davon verbirgt. Dennoch hat diese Methode in einigen Fällen ihre Verwendung, die Dans Lösung nicht abdeckt.
Beide element.getBoundingClientRect()und document.elementFromPoint()sind Teil der CSSOM Working Draft-Spezifikation und werden in mindestens IE 6 und höher sowie in den meisten Desktop-Browsern lange Zeit unterstützt (wenn auch nicht perfekt). Weitere Informationen finden Sie unter Quirksmode für diese Funktionen .
contains()wird verwendet, um festzustellen, ob das von zurückgegebene Element document.elementFromPoint()ein untergeordneter Knoten des Elements ist, das wir auf Sichtbarkeit testen. Es wird auch true zurückgegeben, wenn das zurückgegebene Element dasselbe Element ist. Dies macht die Prüfung nur robuster. Es wird in allen gängigen Browsern unterstützt, wobei Firefox 9.0 der letzte ist, der es hinzufügt. Überprüfen Sie für ältere Firefox-Unterstützung den Verlauf dieser Antwort.
Wenn Sie mehr Punkte um das Element herum auf Sichtbarkeit testen möchten, dh um sicherzustellen, dass das Element nicht durch mehr als beispielsweise 50% abgedeckt ist, würde es nicht viel dauern, den letzten Teil der Antwort anzupassen. Beachten Sie jedoch, dass es wahrscheinlich sehr langsam ist, wenn Sie jedes Pixel überprüfen, um sicherzustellen, dass es zu 100% sichtbar ist.
Wollten Sie doc.documentElement.clientWidth verwenden? Sollte das stattdessen 'document.documentElement' sein? Anders gesagt, dies ist die einzige Methode, die auch für Anwendungsfälle wie das Ausblenden des Inhalts eines Elements für die Barrierefreiheit mithilfe der CSS-Eigenschaft 'clip' funktioniert
Kevin Lamping
@klamping: guter Fang, danke. Ich hatte es direkt aus meinem Code kopiert, für den ich es docals Alias verwendet hatte document. Ja, ich betrachte dies gerne als eine anständige Lösung für die Randfälle.
Andy E
2
Bei mir funktioniert es nicht. Aber inViewport () in der vorherigen Antwort funktioniert in FF.
Satya Prakash
9
Es kann auch nützlich sein, zu überprüfen, ob die Mitte des Elements sichtbar ist, wenn abgerundete Ecken oder eine Transformation angewendet wurden, da die Begrenzungsecken möglicherweise nicht das erwartete Element zurückgeben:element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
Jared
2
Hat bei mir nicht an Eingängen gearbeitet (Chrome Canary 50). Nicht sicher warum, vielleicht einheimische rundere Ecken? Ich musste die Koordinaten leicht reduzieren, damit es el.contains funktioniert (efp (rect.left + 1, rect.top + 1)) || el.contains (efp (rect.right-1, rect.top + 1)) || el.contains (efp (rect.right-1, rect.bottom-1)) || el.contains (efp (rect.left + 1, rect.bottom-1))
Rayjax
65
Ich habe Dans Antwort versucht . Die zur Bestimmung der Grenzen verwendete Algebra bedeutet jedoch, dass das Element sowohl ≤ der Größe des Ansichtsfensters als auch vollständig innerhalb des Ansichtsfensters sein muss, um zu erhalten true, was leicht zu falschen Negativen führt. Wenn Sie feststellen möchten, ob sich überhaupt ein Element im Ansichtsfenster befindet, lautet die Antwort von ryanve knapp, das getestete Element sollte sich jedoch mit dem Ansichtsfenster überschneiden. Versuchen Sie Folgendes :
function isElementInViewport(el){var rect = el.getBoundingClientRect();return rect.bottom >0&&
rect.right >0&&
rect.left <(window.innerWidth || document.documentElement.clientWidth)/* or $(window).width() */&&
rect.top <(window.innerHeight || document.documentElement.clientHeight)/* or $(window).height() */;}
Als öffentlicher Dienst:
Dans Antwort mit den richtigen Berechnungen (Element kann> Fenster sein, insbesondere auf Handybildschirmen) und korrekten jQuery-Tests sowie Hinzufügen von isElementPartiallyInViewport:
By the way, der Unterschied ist zwischen window.innerWidth und document.documentElement.clientWidth dass client / client nicht der Bildlaufleiste enthält, während window.innerWidth / Höhe tut.
function isElementPartiallyInViewport(el){// Special bonus for those using jQueryif(typeof jQuery !=='undefined'&& el instanceof jQuery)
el = el[0];var rect = el.getBoundingClientRect();// DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }var windowHeight =(window.innerHeight || document.documentElement.clientHeight);var windowWidth =(window.innerWidth || document.documentElement.clientWidth);// http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlapvar vertInView =(rect.top <= windowHeight)&&((rect.top + rect.height)>=0);var horInView =(rect.left <= windowWidth)&&((rect.left + rect.width)>=0);return(vertInView && horInView);}// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewportfunction isElementInViewport (el){// Special bonus for those using jQueryif(typeof jQuery !=='undefined'&& el instanceof jQuery)
el = el[0];var rect = el.getBoundingClientRect();var windowHeight =(window.innerHeight || document.documentElement.clientHeight);var windowWidth =(window.innerWidth || document.documentElement.clientWidth);return((rect.left >=0)&&(rect.top >=0)&&((rect.left + rect.width)<= windowWidth)&&((rect.top + rect.height)<= windowHeight));}function fnIsVis(ele){var inVpFull = isElementInViewport(ele);var inVpPartial = isElementPartiallyInViewport(ele);
console.clear();
console.log("Fully in viewport: "+ inVpFull);
console.log("Partially in viewport: "+ inVpPartial);}
isElementPartiallyInViewportist auch sehr nützlich. Schön.
RJ Cuthbertson
Für isElementInViewport (e): Ihr Code lädt nicht einmal Bilder. Dieser ist korrekt: Funktion isElementInViewport (e) {var t = e.getBoundingClientRect (); return t.top> = 0 && t.left> = 0 && t.bottom <= (window.innerHeight || document.documentElement.clientHeight) && t.right <= (window.innerWidth || document.documentElement.clientWidth) }
Arun Chauhan
1
@Arun chauhan: Keiner meiner Codes lädt Bilder. Warum sollte das so sein? Die Formel ist korrekt.
Stefan Steiger
1
@targumon: Der Grund ist die Unterstützung alter Browser.
Stefan Steiger
1
@StefanSteiger laut MDN wird es seit IE9 unterstützt, so dass es praktisch sicher ist (zumindest in meinem Fall), nur window.innerHeight direkt zu verwenden. Vielen Dank!
Meine Lösung ist gieriger und schneller. Wenn ein Element ein Pixel im Ansichtsfenster hat, wird false zurückgegeben.
Eric Chen
1
Ich mag das. Prägnant. Sie können die Leerzeichen zwischen Funktionsname und Klammer sowie zwischen Klammer und Klammer in der ersten Zeile entfernen. Ich mochte diese Räume nie. Vielleicht ist es nur mein Texteditor, der alles farbcodiert, was das Lesen noch erleichtert. Funktion aaa (arg) {Anweisungen} Ich weiß, dass es nicht schneller ausgeführt wird, sondern unter Minimierung fällt.
YK
21
Ich fand es beunruhigend, dass es keine jQuery- zentrierte Version der verfügbaren Funktionalität gab. Als ich auf Dans Lösung stieß, erspähte ich die Gelegenheit, etwas für Leute bereitzustellen, die gerne im jQuery OO-Stil programmieren. Es ist schön und bissig und wirkt wie ein Zauber für mich.
Bada Bing Bada Boom
$.fn.inView =function(){if(!this.length)returnfalse;var rect =this.get(0).getBoundingClientRect();return(
rect.top >=0&&
rect.left >=0&&
rect.bottom <=(window.innerHeight || document.documentElement.clientHeight)&&
rect.right <=(window.innerWidth || document.documentElement.clientWidth));};// Additional examples for other use cases// Is true false whether an array of elements are all in view
$.fn.allInView =function(){var all =[];this.forEach(function(){
all.push( $(this).inView());});return all.indexOf(false)===-1;};// Only the class elements in view
$('.some-class').filter(function(){return $(this).inView();});// Only the class elements not in view
$('.some-class').filter(function(){return!$(this).inView();});
Verwendungszweck
$(window).on('scroll',function(){if( $('footer').inView()){// Do cool stuff}});
Würde die geschweifte Klammer ausreichen, um die if-Anweisung zu schließen?
Calasyr
1
Ich konnte es nicht mit mehreren Elementen einer identischen Klasse zum Laufen bringen.
The Whiz of Oz
1
@TheWhizofOz Ich habe meine Antwort aktualisiert, um Beispiele für die anderen möglichen Anwendungsfälle zu geben, die Sie angesprochen haben. viel Glück.
Diese Lösung benötigt eine Polyfüllung, da Safari, Opera und Internet Explorer dies noch nicht unterstützen (die Polyfüllung ist in der Lösung enthalten).
In dieser Lösung befindet sich eine Box außerhalb der Sicht, die das Ziel ist (beobachtet). Wenn es angezeigt wird, ist die Schaltfläche oben in der Kopfzeile ausgeblendet. Es wird angezeigt, sobald das Feld die Ansicht verlässt.
const buttonToHide = document.querySelector('button');const hideWhenBoxInView =newIntersectionObserver((entries)=>{if(entries[0].intersectionRatio <=0){// If not in view
buttonToHide.style.display ="inherit";}else{
buttonToHide.style.display ="none";}});
hideWhenBoxInView.observe(document.getElementById('box'));
<scriptsrc="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script><header><button>NAVIGATION BUTTON TO HIDE</button></header><divclass="wrapper"><divid="box"></div></div>
Gute Umsetzung, und nach dem Link in dieser Antwort es sollte auf Safari arbeitet durch Zugabe <!DOCTYPE html>zu dem HTML
Alon Eitan
Beachten Sie, dass dies IntersectionObservereine experimentelle Funktion ist (die sich in Zukunft ändern kann).
Karthik Chintala
2
@KarthikChintala - es wird in jedem Browser außer IE unterstützt - und es ist auch eine Polyfüllung verfügbar.
Randy Casburn
Behandelt die Frage des OP nicht, da nur Änderungen erkannt werden : Der IntersectionObserverRückruf wird erst ausgelöst, nachdem das Ziel relativ zur Wurzel bewegt wurde.
Brandon Hill
Wenn ein aufrufendes observeEreignis ausgelöst wird, werden Sie sofort über den aktuellen Schnittpunktstatus des verfolgten Elements informiert. Also irgendwie - es spricht an.
Mesqalito
8
Alle Antworten, auf die ich hier gestoßen bin, prüfen nur, ob sich das Element im aktuellen Ansichtsfenster befindet . Das heißt aber nicht, dass es sichtbar ist .
Was ist, wenn sich das angegebene Element in einem Div mit überfülltem Inhalt befindet und nicht mehr sichtbar ist?
Um dies zu lösen, müssten Sie überprüfen, ob das Element von allen Eltern enthalten ist.
Meine Lösung macht genau das:
Außerdem können Sie festlegen, wie viel des Elements sichtbar sein muss.
Element.prototype.isVisible =function(percentX, percentY){var tolerance =0.01;//needed because the rects returned by getBoundingClientRect provide the position up to 10 decimalsif(percentX ==null){
percentX =100;}if(percentY ==null){
percentY =100;}var elementRect =this.getBoundingClientRect();var parentRects =[];var element =this;while(element.parentElement !=null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;}var visibleInAllParents = parentRects.every(function(parentRect){var visiblePixelX =Math.min(elementRect.right, parentRect.right)-Math.max(elementRect.left, parentRect.left);var visiblePixelY =Math.min(elementRect.bottom, parentRect.bottom)-Math.max(elementRect.top, parentRect.top);var visiblePercentageX = visiblePixelX / elementRect.width *100;var visiblePercentageY = visiblePixelY / elementRect.height *100;return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;});return visibleInAllParents;};
Diese Lösung ignorierte die Tatsache, dass Elemente aufgrund anderer Fakten wie z opacity: 0.
Ich habe diese Lösung in Chrome und Internet Explorer 11 getestet.
Ich finde, dass die hier akzeptierte Antwort für die meisten Anwendungsfälle zu kompliziert ist. Dieser Code macht den Job gut (mit jQuery) und unterscheidet zwischen vollständig sichtbaren und teilweise sichtbaren Elementen:
var element = $("#element");var topOfElement = element.offset().top;var bottomOfElement = element.offset().top + element.outerHeight(true);var $window = $(window);
$window.bind('scroll',function(){var scrollTopPosition = $window.scrollTop()+$window.height();var windowScrollTop = $window.scrollTop()if(windowScrollTop > topOfElement && windowScrollTop < bottomOfElement){// Element is partially visible (above viewable area)
console.log("Element is partially visible (above viewable area)");}elseif(windowScrollTop > bottomOfElement && windowScrollTop > topOfElement){// Element is hidden (above viewable area)
console.log("Element is hidden (above viewable area)");}elseif(scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement){// Element is hidden (below viewable area)
console.log("Element is hidden (below viewable area)");}elseif(scrollTopPosition < bottomOfElement && scrollTopPosition > topOfElement){// Element is partially visible (below viewable area)
console.log("Element is partially visible (below viewable area)");}else{// Element is completely visible
console.log("Element is completely visible");}});
Wie verhält sich das in mobilen Browsern? Die meisten von ihnen sind in Bezug auf das Ansichtsfenster fehlerhaft. Der Header wird beim Scrollen nach oben oder unten verschoben, und das Verhalten beim Anzeigen der Tastatur ist unterschiedlich, je nachdem, ob es sich um Android oder iOS usw. handelt.
Kev
@Kev Sollte gut funktionieren, je nachdem, wann Sie diese Methode aufrufen. Wenn Sie es aufrufen und dann die Fenstergröße ändern, ist das Ergebnis möglicherweise nicht mehr korrekt. Sie können es bei jedem Größenänderungsereignis aufrufen, abhängig von der Art der gewünschten Funktionalität. Sie können gerne eine separate Frage zu Ihrem speziellen Anwendungsfall stellen und mich hier anpingen.
Leonheess
3
Ich denke, dies ist ein funktionalerer Weg, dies zu tun.
Dans Antwort funktioniert nicht in einem rekursiven Kontext.
Diese Funktion löst das Problem, wenn sich Ihr Element in anderen scrollbaren Divs befindet, indem alle Ebenen rekursiv bis zum HTML-Tag getestet werden und beim ersten false angehalten wird.
/**
* fullVisible=true only returns true if the all object rect is visible
*/function isReallyVisible(el, fullVisible){if( el.tagName =="HTML")returntrue;var parentRect=el.parentNode.getBoundingClientRect();var rect = arguments[2]|| el.getBoundingClientRect();return(( fullVisible ? rect.top >= parentRect.top : rect.bottom > parentRect.top )&&( fullVisible ? rect.left >= parentRect.left : rect.right > parentRect.left )&&( fullVisible ? rect.bottom <= parentRect.bottom : rect.top < parentRect.bottom )&&( fullVisible ? rect.right <= parentRect.right : rect.left < parentRect.right )&&
isReallyVisible(el.parentNode, fullVisible, rect));};
Die am meisten akzeptierten Antworten funktionieren beim Zoomen in Google Chrome unter Android nicht. In Kombination mit Dans Antwort muss visualViewport verwendet werden, um Chrome unter Android zu berücksichtigen . Das folgende Beispiel berücksichtigt nur die vertikale Prüfung und verwendet jQuery für die Fensterhöhe:
var visibleY =function(el){var top = el.getBoundingClientRect().top, rect, el = el.parentNode;do{
rect = el.getBoundingClientRect();if(top <= rect.bottom ===false)returnfalse;
el = el.parentNode;}while(el != document.body);// Check it's within the document viewportreturn top <= document.documentElement.clientHeight;};
Ich musste nur überprüfen, ob es auf der Y-Achse sichtbar ist (für eine scrollende Ajax-Funktion zum Laden weiterer Datensätze).
Ich verwende es so, dass ich beim Scrollen des Elements in die Ansicht eine Klasse hinzufüge, die eine CSS-Keyframe-Animation auslöst. Es ist ziemlich einfach und funktioniert besonders gut, wenn Sie mehr als 10 Dinge auf einer Seite bedingt animieren müssen.
Sie sollten auf jeden Fall $window = $(window)außerhalb des Scroll-
Handlers zwischenspeichern
2
Die meisten Verwendungen in früheren Antworten schlagen an folgenden Punkten fehl:
-Wenn ein Pixel eines Elements sichtbar ist, aber keine " Ecke ",
-Wenn ein Element größer als das Ansichtsfenster und zentriert ist ,
- Die meisten von ihnen suchen nur nach einem einzelnen Element in einem Dokument oder Fenster .
Nun, für all diese Probleme habe ich eine Lösung und die positiven Seiten sind:
-Sie können zurückkehren, visiblewenn nur ein Pixel von einer Seite angezeigt wird und keine Ecke ist.
-Sie können immer noch zurückkehren, visiblewenn das Element größer als das Ansichtsfenster ist.
-Sie können Ihre auswählen parent elementoder Sie können sie automatisch auswählen lassen,
- Arbeitet auch an dynamisch hinzugefügten Elementen .
Wenn Sie die folgenden Ausschnitte überprüfen, werden Sie feststellen, dass der Unterschied bei der Verwendung overflow-scrollim Container des Elements keine Probleme verursacht und dass im Gegensatz zu anderen Antworten hier ein Pixel von einer Seite angezeigt wird oder wenn ein Element größer als das Ansichtsfenster ist und wir das Innere sehen Pixel des Elements funktioniert es noch.
Die Verwendung ist einfach:
// For checking element visibility from any sides
isVisible(element)// For checking elements visibility in a parent you would like to checkvar parent = document;// Assuming you check if 'element' inside 'document'
isVisible(element, parent)// For checking elements visibility even if it's bigger than viewport
isVisible(element,null,true)// Without parent choice
isVisible(element, parent,true)// With parent choice
Eine Demonstration ohne crossSearchAlgorithmdiese ist nützlich für Elemente, die größer als das Ansichtsfenster sind. Überprüfen Sie die inneren Pixel von Element3, um Folgendes zu sehen:
function isVisible(element, parent, crossSearchAlgorithm){var rect = element.getBoundingClientRect(),
prect =(parent !=undefined)? parent.getBoundingClientRect(): element.parentNode.getBoundingClientRect(),
csa =(crossSearchAlgorithm !=undefined)? crossSearchAlgorithm :false,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom){returnfalse;}var flag =false;// Return true if left to right any border pixel reachedfor(var x = rect.left; x < rect.right; x++){if(element.contains(efp(rect.top, x))|| element.contains(efp(rect.bottom, x))){
flag =true;break;}}// Return true if top to bottom any border pixel reachedif(flag ==false){for(var y = rect.top; y < rect.bottom; y++){if(element.contains(efp(rect.left, y))|| element.contains(efp(rect.right, y))){
flag =true;break;}}}if(csa){// Another algorithm to check if element is centered and bigger than viewportif(flag ==false){var x = rect.left;var y = rect.top;// From top left to bottom rightwhile(x < rect.right || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x < rect.right){ x++;}if(y < rect.bottom){ y++;}}if(flag ==false){
x = rect.right;
y = rect.top;// From top right to bottom leftwhile(x > rect.left || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x > rect.left){ x--;}if(y < rect.bottom){ y++;}}}}}return flag;}// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll",function(){var elementList = document.getElementsByClassName("element");var console = document.getElementById('console');for(var i=0; i < elementList.length; i++){// I did not define parent, so it will be element's parentif(isVisible(elementList[i])){
console.innerHTML ="Element with id["+ elementList[i].id +"] is visible!";break;}else{
console.innerHTML ="Element with id["+ elementList[i].id +"] is hidden!";}}});// Dynamically added elementsfor(var i=4; i <=6; i++){var newElement = document.createElement("div");
newElement.id ="element"+ i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);}
Sie sehen, wenn Sie sich innerhalb des Elements3 befinden, kann es nicht erkennen, ob es sichtbar ist oder nicht, da wir nur prüfen, ob das Element von Seiten oder Ecken sichtbar ist .
Und dies beinhaltet crossSearchAlgorithm, dass Sie immer noch zurückkehren können, visiblewenn das Element größer als das Ansichtsfenster ist:
function isVisible(element, parent, crossSearchAlgorithm){var rect = element.getBoundingClientRect(),
prect =(parent !=undefined)? parent.getBoundingClientRect(): element.parentNode.getBoundingClientRect(),
csa =(crossSearchAlgorithm !=undefined)? crossSearchAlgorithm :false,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom){returnfalse;}var flag =false;// Return true if left to right any border pixel reachedfor(var x = rect.left; x < rect.right; x++){if(element.contains(efp(rect.top, x))|| element.contains(efp(rect.bottom, x))){
flag =true;break;}}// Return true if top to bottom any border pixel reachedif(flag ==false){for(var y = rect.top; y < rect.bottom; y++){if(element.contains(efp(rect.left, y))|| element.contains(efp(rect.right, y))){
flag =true;break;}}}if(csa){// Another algorithm to check if element is centered and bigger than viewportif(flag ==false){var x = rect.left;var y = rect.top;// From top left to bottom rightwhile(x < rect.right || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x < rect.right){ x++;}if(y < rect.bottom){ y++;}}if(flag ==false){
x = rect.right;
y = rect.top;// From top right to bottom leftwhile(x > rect.left || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x > rect.left){ x--;}if(y < rect.bottom){ y++;}}}}}return flag;}// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll",function(){var elementList = document.getElementsByClassName("element");var console = document.getElementById('console');for(var i=0; i < elementList.length; i++){// I did not define parent so it will be element's parent// and it will do crossSearchAlgorithmif(isVisible(elementList[i],null,true)){
console.innerHTML ="Element with id["+ elementList[i].id +"] is visible!";break;}else{
console.innerHTML ="Element with id["+ elementList[i].id +"] is hidden!";}}});// Dynamically added elementsfor(var i=4; i <=6; i++){var newElement = document.createElement("div");
newElement.id ="element"+ i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);}
Dieser Code dient zur genaueren Information, ob ein Teil des Elements in der Ansicht angezeigt wird oder nicht. Verwenden Sie diese Option nicht für Leistungsoptionen oder nur für vertikale Folien! Dieser Code ist beim Zeichnen von Fällen effektiver.
Ich hatte die gleiche Frage und fand sie mit getBoundingClientRect () heraus.
Dieser Code ist vollständig "generisch" und muss nur einmal geschrieben werden, damit er funktioniert (Sie müssen ihn nicht für jedes Element ausschreiben, von dem Sie wissen möchten, dass es sich im Ansichtsfenster befindet).
Dieser Code prüft nur, ob er sich vertikal im Ansichtsfenster befindet, nicht horizontal . In diesem Fall enthält die Variable (Array) 'Elemente' alle Elemente, die Sie als vertikal im Ansichtsfenster überprüfen möchten. Nehmen Sie also alle gewünschten Elemente an einer beliebigen Stelle und speichern Sie sie dort.
Die 'for-Schleife' durchläuft jedes Element und prüft, ob es sich vertikal im Ansichtsfenster befindet. Dieser Code wird jedes Mal ausgeführt, wenn der Benutzer einen Bildlauf durchführt! Wenn getBoudingClientRect (). Top weniger als 3/4 des Ansichtsfensters beträgt (das Element ist ein Viertel im Ansichtsfenster), wird es als "im Ansichtsfenster" registriert.
Da der Code generisch ist, möchten Sie wissen, welches Element sich im Ansichtsfenster befindet. Um dies herauszufinden, können Sie es anhand eines benutzerdefinierten Attributs, eines Knotennamens, einer ID, eines Klassennamens usw. ermitteln.
Hier ist mein Code (sagen Sie mir, wenn er nicht funktioniert; er wurde in Internet Explorer 11, Firefox 40.0.3, Chrome Version 45.0.2454.85 m, Opera 31.0.1889.174 und Edge mit Windows 10 getestet [noch nicht Safari ]) ...
// Scrolling handlers...
window.onscroll =function(){var elements = document.getElementById('whatever').getElementsByClassName('whatever');for(var i =0; i != elements.length; i++){if(elements[i].getBoundingClientRect().top <= window.innerHeight*0.75&&
elements[i].getBoundingClientRect().top >0){
console.log(elements[i].nodeName +' '+
elements[i].className +' '+
elements[i].id +' is in the viewport; proceed with whatever code you want to do here.');}};
Alle Antworten hier bestimmen, ob das Element vollständig im Ansichtsfenster enthalten ist und nicht nur auf irgendeine Weise sichtbar ist. Wenn beispielsweise nur die Hälfte eines Bildes am unteren Rand der Ansicht sichtbar ist, schlagen die Lösungen hier fehl, wenn man bedenkt, dass "außen".
Ich hatte einen Anwendungsfall, in dem ich verzögert über lade IntersectionObserver, aber aufgrund von Animationen, die während des Pop-Ins auftreten, wollte ich keine Bilder beobachten, die bereits beim Laden der Seite geschnitten wurden. Dazu habe ich folgenden Code verwendet:
Hierbei wird im Wesentlichen überprüft, ob sich die obere oder untere Grenze unabhängig voneinander im Ansichtsfenster befindet. Das gegenüberliegende Ende kann außerhalb sein, aber solange ein Ende innen ist, ist es zumindest teilweise "sichtbar".
Antworten:
Update: Die Zeit vergeht und unsere Browser auch. Diese Technik wird nicht mehr empfohlen und Sie sollten Dans Lösung verwenden, wenn Sie die Version von Internet Explorer nicht vor 7 unterstützen müssen.
Ursprüngliche Lösung (jetzt veraltet):
Dadurch wird überprüft, ob das Element im aktuellen Ansichtsfenster vollständig sichtbar ist:
Sie können dies einfach ändern, um festzustellen, ob ein Teil des Elements im Ansichtsfenster sichtbar ist:
quelle
getBoundingClientRect
speziell für die Suche nach Elementkoordinaten erstellt ... Warum sollten wir sie nicht verwenden?Jetzt unterstützen die meisten Browser die Methode getBoundingClientRect , die zur Best Practice geworden ist. Die Verwendung einer alten Antwort ist sehr langsam , nicht genau und weist mehrere Fehler auf .
Die als richtig gewählte Lösung ist fast nie präzise . Sie können mehr über seine Fehler lesen .
Diese Lösung wurde auf Internet Explorer 7 (und höher), iOS 5 (und höher) Safari, Android 2.0 (Eclair) und höher, BlackBerry, Opera Mobile und Internet Explorer Mobile 9 getestet .
Wie benutzt man:
Sie können sicher sein, dass die oben angegebene Funktion zum Zeitpunkt des Aufrufs die richtige Antwort zurückgibt. Wie steht es jedoch mit der Sichtbarkeit des Elements als Ereignis?
Platzieren Sie den folgenden Code am unteren Rand Ihres
<body>
Tags:Wenn Sie DOM-Änderungen vornehmen, können diese natürlich die Sichtbarkeit Ihres Elements ändern.
Richtlinien und häufige Fallstricke:
Möglicherweise müssen Sie den Seitenzoom / die Prise des Mobilgeräts verfolgen? jQuery sollte den Cross-Browser Zoom / Pinch verarbeiten , andernfalls sollte der erste oder zweite Link Ihnen helfen.
Wenn Sie das DOM ändern , kann dies die Sichtbarkeit des Elements beeinträchtigen. Sie sollten die Kontrolle darüber übernehmen und
handler()
manuell anrufen . Leider haben wir kein browserübergreifendesonrepaint
Ereignis. Auf der anderen Seite können wir Optimierungen vornehmen und nur DOM-Änderungen überprüfen, die die Sichtbarkeit eines Elements ändern können.Verwenden Sie es niemals nur in jQuery $ (document) .ready () , da in diesem Moment keine Garantie für CSS besteht . Ihr Code kann lokal mit Ihrem CSS auf einer Festplatte arbeiten, aber sobald er auf einem Remote-Server installiert ist, schlägt er fehl.
Nach dem
DOMContentLoaded
Auslösen werden Stile angewendet , aber die Bilder werden noch nicht geladen . Wir sollten also denwindow.onload
Ereignis-Listener hinzufügen .Wir können das Zoom / Pinch-Ereignis noch nicht erfassen.
Der letzte Ausweg könnte der folgende Code sein:
Sie können die fantastische Funktion pageVisibiliy der HTML5-API verwenden, wenn Sie sich dafür interessieren, ob die Registerkarte mit Ihrer Webseite aktiv und sichtbar ist.
TODO: Diese Methode behandelt nicht zwei Situationen:
z-index
overflow-scroll
im Container des Elementsquelle
return (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
isElementInViewport(document.getElementById('elem'))
) und nicht das jQuery-Objekt (zisElementInViewport($("#elem))
. B. ) zu übergeben. Das jQuery-Äquivalent lautet[0]
wie folgt :isElementInViewport($("#elem)[0])
.el is not defined
Aktualisieren
In modernen Browsern möchten Sie möglicherweise die Intersection Observer-API ausprobieren, die die folgenden Vorteile bietet:
Intersection Observer ist auf dem Weg zu einem vollwertigen Standard und wird bereits in Chrome 51+, Edge 15+ und Firefox 55+ unterstützt und befindet sich in der Entwicklung für Safari. Es gibt auch eine Polyfüllung .
Vorherige Antwort
Es gibt einige Probleme mit der Antwort von Dan , die es für einige Situationen zu einem ungeeigneten Ansatz machen könnten. Einige dieser Probleme werden in seiner Antwort am unteren Rand darauf hingewiesen, dass sein Code falsch positive Ergebnisse für Elemente liefert, die:
clip
Eigenschaft ausgeblendet wurdenDiese Einschränkungen werden in den folgenden Ergebnissen eines einfachen Tests gezeigt :
Die Lösung:
isElementVisible()
Hier finden Sie eine Lösung für diese Probleme mit dem folgenden Testergebnis und einer Erläuterung einiger Teile des Codes.
Und das Ergebnis:
Zusätzliche Bemerkungen
Diese Methode ist jedoch nicht ohne Einschränkungen. Zum Beispiel würde ein Element, das mit einem niedrigeren Z-Index als ein anderes Element an derselben Stelle getestet wird, als versteckt identifiziert, selbst wenn das vordere Element tatsächlich keinen Teil davon verbirgt. Dennoch hat diese Methode in einigen Fällen ihre Verwendung, die Dans Lösung nicht abdeckt.
Beide
element.getBoundingClientRect()
unddocument.elementFromPoint()
sind Teil der CSSOM Working Draft-Spezifikation und werden in mindestens IE 6 und höher sowie in den meisten Desktop-Browsern lange Zeit unterstützt (wenn auch nicht perfekt). Weitere Informationen finden Sie unter Quirksmode für diese Funktionen .contains()
wird verwendet, um festzustellen, ob das von zurückgegebene Elementdocument.elementFromPoint()
ein untergeordneter Knoten des Elements ist, das wir auf Sichtbarkeit testen. Es wird auch true zurückgegeben, wenn das zurückgegebene Element dasselbe Element ist. Dies macht die Prüfung nur robuster. Es wird in allen gängigen Browsern unterstützt, wobei Firefox 9.0 der letzte ist, der es hinzufügt. Überprüfen Sie für ältere Firefox-Unterstützung den Verlauf dieser Antwort.Wenn Sie mehr Punkte um das Element herum auf Sichtbarkeit testen möchten, dh um sicherzustellen, dass das Element nicht durch mehr als beispielsweise 50% abgedeckt ist, würde es nicht viel dauern, den letzten Teil der Antwort anzupassen. Beachten Sie jedoch, dass es wahrscheinlich sehr langsam ist, wenn Sie jedes Pixel überprüfen, um sicherzustellen, dass es zu 100% sichtbar ist.
quelle
doc
als Alias verwendet hattedocument
. Ja, ich betrachte dies gerne als eine anständige Lösung für die Randfälle.element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
Ich habe Dans Antwort versucht . Die zur Bestimmung der Grenzen verwendete Algebra bedeutet jedoch, dass das Element sowohl ≤ der Größe des Ansichtsfensters als auch vollständig innerhalb des Ansichtsfensters sein muss, um zu erhalten
true
, was leicht zu falschen Negativen führt. Wenn Sie feststellen möchten, ob sich überhaupt ein Element im Ansichtsfenster befindet, lautet die Antwort von ryanve knapp, das getestete Element sollte sich jedoch mit dem Ansichtsfenster überschneiden. Versuchen Sie Folgendes :quelle
Als öffentlicher Dienst:
Dans Antwort mit den richtigen Berechnungen (Element kann> Fenster sein, insbesondere auf Handybildschirmen) und korrekten jQuery-Tests sowie Hinzufügen von isElementPartiallyInViewport:
By the way, der Unterschied ist zwischen window.innerWidth und document.documentElement.clientWidth dass client / client nicht der Bildlaufleiste enthält, während window.innerWidth / Höhe tut.
Testfall
quelle
isElementPartiallyInViewport
ist auch sehr nützlich. Schön.Siehe die Quelle kurz davor , die verwendet getBoundingClientRect . Es ist wie:
Es wird zurückgegeben,
true
wenn sich ein Teil des Elements im Ansichtsfenster befindet.quelle
Meine kürzere und schnellere Version:
Und eine jsFiddle nach Bedarf: https://jsfiddle.net/on1g619L/1/
quelle
Ich fand es beunruhigend, dass es keine jQuery- zentrierte Version der verfügbaren Funktionalität gab. Als ich auf Dans Lösung stieß, erspähte ich die Gelegenheit, etwas für Leute bereitzustellen, die gerne im jQuery OO-Stil programmieren. Es ist schön und bissig und wirkt wie ein Zauber für mich.
Bada Bing Bada Boom
Verwendungszweck
quelle
Die neue Intersection Observer API geht diese Frage sehr direkt an.
Diese Lösung benötigt eine Polyfüllung, da Safari, Opera und Internet Explorer dies noch nicht unterstützen (die Polyfüllung ist in der Lösung enthalten).
In dieser Lösung befindet sich eine Box außerhalb der Sicht, die das Ziel ist (beobachtet). Wenn es angezeigt wird, ist die Schaltfläche oben in der Kopfzeile ausgeblendet. Es wird angezeigt, sobald das Feld die Ansicht verlässt.
quelle
<!DOCTYPE html>
zu dem HTMLIntersectionObserver
eine experimentelle Funktion ist (die sich in Zukunft ändern kann).IntersectionObserver
Rückruf wird erst ausgelöst, nachdem das Ziel relativ zur Wurzel bewegt wurde.observe
Ereignis ausgelöst wird, werden Sie sofort über den aktuellen Schnittpunktstatus des verfolgten Elements informiert. Also irgendwie - es spricht an.Alle Antworten, auf die ich hier gestoßen bin, prüfen nur, ob sich das Element im aktuellen Ansichtsfenster befindet . Das heißt aber nicht, dass es sichtbar ist .
Was ist, wenn sich das angegebene Element in einem Div mit überfülltem Inhalt befindet und nicht mehr sichtbar ist?
Um dies zu lösen, müssten Sie überprüfen, ob das Element von allen Eltern enthalten ist.
Meine Lösung macht genau das:
Außerdem können Sie festlegen, wie viel des Elements sichtbar sein muss.
Diese Lösung ignorierte die Tatsache, dass Elemente aufgrund anderer Fakten wie z
opacity: 0
.Ich habe diese Lösung in Chrome und Internet Explorer 11 getestet.
quelle
Ich finde, dass die hier akzeptierte Antwort für die meisten Anwendungsfälle zu kompliziert ist. Dieser Code macht den Job gut (mit jQuery) und unterscheidet zwischen vollständig sichtbaren und teilweise sichtbaren Elementen:
quelle
$window = $(window)
außerhalb des Scroll-Handlers zwischenspeichern.Die einfachste Lösung als Unterstützung von Element.getBoundingClientRect () ist perfekt geworden :
quelle
Ich denke, dies ist ein funktionalerer Weg, dies zu tun. Dans Antwort funktioniert nicht in einem rekursiven Kontext.
Diese Funktion löst das Problem, wenn sich Ihr Element in anderen scrollbaren Divs befindet, indem alle Ebenen rekursiv bis zum HTML-Tag getestet werden und beim ersten false angehalten wird.
quelle
Die am meisten akzeptierten Antworten funktionieren beim Zoomen in Google Chrome unter Android nicht. In Kombination mit Dans Antwort muss visualViewport verwendet werden, um Chrome unter Android zu berücksichtigen . Das folgende Beispiel berücksichtigt nur die vertikale Prüfung und verwendet jQuery für die Fensterhöhe:
quelle
Hier ist meine Lösung. Es funktioniert, wenn ein Element in einem scrollbaren Container versteckt ist.
Hier ist eine Demo (versuchen Sie, die Größe des Fensters zu ändern)
Ich musste nur überprüfen, ob es auf der Y-Achse sichtbar ist (für eine scrollende Ajax-Funktion zum Laden weiterer Datensätze).
quelle
Basierend auf Dans Lösung habe ich versucht, die Implementierung zu bereinigen, damit es einfacher ist, sie mehrmals auf derselben Seite zu verwenden:
Ich verwende es so, dass ich beim Scrollen des Elements in die Ansicht eine Klasse hinzufüge, die eine CSS-Keyframe-Animation auslöst. Es ist ziemlich einfach und funktioniert besonders gut, wenn Sie mehr als 10 Dinge auf einer Seite bedingt animieren müssen.
quelle
$window = $(window)
außerhalb des Scroll-Die meisten Verwendungen in früheren Antworten schlagen an folgenden Punkten fehl:
Nun, für all diese Probleme habe ich eine Lösung und die positiven Seiten sind:
Wenn Sie die folgenden Ausschnitte überprüfen, werden Sie feststellen, dass der Unterschied bei der Verwendung
overflow-scroll
im Container des Elements keine Probleme verursacht und dass im Gegensatz zu anderen Antworten hier ein Pixel von einer Seite angezeigt wird oder wenn ein Element größer als das Ansichtsfenster ist und wir das Innere sehen Pixel des Elements funktioniert es noch.Die Verwendung ist einfach:
Eine Demonstration ohne
crossSearchAlgorithm
diese ist nützlich für Elemente, die größer als das Ansichtsfenster sind. Überprüfen Sie die inneren Pixel von Element3, um Folgendes zu sehen:Code-Snippet anzeigen
Sie sehen, wenn Sie sich innerhalb des Elements3 befinden, kann es nicht erkennen, ob es sichtbar ist oder nicht, da wir nur prüfen, ob das Element von Seiten oder Ecken sichtbar ist .
Und dies beinhaltet
crossSearchAlgorithm
, dass Sie immer noch zurückkehren können,visible
wenn das Element größer als das Ansichtsfenster ist:Code-Snippet anzeigen
JSFiddle zum Spielen: http://jsfiddle.net/BerkerYuceer/grk5az2c/
Dieser Code dient zur genaueren Information, ob ein Teil des Elements in der Ansicht angezeigt wird oder nicht. Verwenden Sie diese Option nicht für Leistungsoptionen oder nur für vertikale Folien! Dieser Code ist beim Zeichnen von Fällen effektiver.
quelle
Eine bessere Lösung:
quelle
So einfach wie es nur geht, IMO:
quelle
Hier ist eine Funktion, die angibt, ob ein Element im aktuellen Ansichtsfenster eines übergeordneten Elements sichtbar ist:
quelle
Dies prüft, ob ein Element zumindest teilweise sichtbar ist (vertikale Abmessung):
quelle
Ich hatte die gleiche Frage und fand sie mit getBoundingClientRect () heraus.
Dieser Code ist vollständig "generisch" und muss nur einmal geschrieben werden, damit er funktioniert (Sie müssen ihn nicht für jedes Element ausschreiben, von dem Sie wissen möchten, dass es sich im Ansichtsfenster befindet).
Dieser Code prüft nur, ob er sich vertikal im Ansichtsfenster befindet, nicht horizontal . In diesem Fall enthält die Variable (Array) 'Elemente' alle Elemente, die Sie als vertikal im Ansichtsfenster überprüfen möchten. Nehmen Sie also alle gewünschten Elemente an einer beliebigen Stelle und speichern Sie sie dort.
Die 'for-Schleife' durchläuft jedes Element und prüft, ob es sich vertikal im Ansichtsfenster befindet. Dieser Code wird jedes Mal ausgeführt, wenn der Benutzer einen Bildlauf durchführt! Wenn getBoudingClientRect (). Top weniger als 3/4 des Ansichtsfensters beträgt (das Element ist ein Viertel im Ansichtsfenster), wird es als "im Ansichtsfenster" registriert.
Da der Code generisch ist, möchten Sie wissen, welches Element sich im Ansichtsfenster befindet. Um dies herauszufinden, können Sie es anhand eines benutzerdefinierten Attributs, eines Knotennamens, einer ID, eines Klassennamens usw. ermitteln.
Hier ist mein Code (sagen Sie mir, wenn er nicht funktioniert; er wurde in Internet Explorer 11, Firefox 40.0.3, Chrome Version 45.0.2454.85 m, Opera 31.0.1889.174 und Edge mit Windows 10 getestet [noch nicht Safari ]) ...
quelle
Dies ist die einfache und kleine Lösung, die für mich funktioniert hat.
Beispiel : Sie möchten sehen, ob das Element im übergeordneten Element mit Überlauf-Bildlauf sichtbar ist.
quelle
Alle Antworten hier bestimmen, ob das Element vollständig im Ansichtsfenster enthalten ist und nicht nur auf irgendeine Weise sichtbar ist. Wenn beispielsweise nur die Hälfte eines Bildes am unteren Rand der Ansicht sichtbar ist, schlagen die Lösungen hier fehl, wenn man bedenkt, dass "außen".
Ich hatte einen Anwendungsfall, in dem ich verzögert über lade
IntersectionObserver
, aber aufgrund von Animationen, die während des Pop-Ins auftreten, wollte ich keine Bilder beobachten, die bereits beim Laden der Seite geschnitten wurden. Dazu habe ich folgenden Code verwendet:Hierbei wird im Wesentlichen überprüft, ob sich die obere oder untere Grenze unabhängig voneinander im Ansichtsfenster befindet. Das gegenüberliegende Ende kann außerhalb sein, aber solange ein Ende innen ist, ist es zumindest teilweise "sichtbar".
quelle
Ich benutze diese Funktion (sie prüft nur, ob das y im Bildschirm ist, da das x die meiste Zeit nicht benötigt wird)
quelle
Für eine ähnliche Herausforderung hat mir dieser Kern sehr gut gefallen, der eine Polyfüllung für scrollIntoViewIfNeeded () verfügbar macht .
In diesem Block befindet sich alles notwendige Kung Fu, um zu antworten:
this
bezieht sich auf das Element, das Sie wissen möchten, wenn es zum Beispiel ist,overTop
oderoverBottom
- Sie sollten nur die Drift bekommen ...quelle