Wie überprüfe ich, ob das Element nach dem Scrollen sichtbar ist?

1170

Ich lade Elemente über AJAX. Einige von ihnen sind nur sichtbar, wenn Sie die Seite nach unten scrollen.
Kann ich auf irgendeine Weise feststellen, ob sich ein Element jetzt im sichtbaren Teil der Seite befindet?

yoavf
quelle
42
Er möchte, dass eine Methode weiß, ob ein bestimmtes Element im Browserfenster angezeigt wird oder ob der Benutzer einen Bildlauf durchführen muss, um es anzuzeigen.
Romain Linsolas
1
Um zu überprüfen, ob ein Element in einem Container vollständig sichtbar ist, fügen Sie einfach einen zusätzlichen Auswahlparameter hinzu und verwenden Sie den Elementcode erneut. Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
Lifes
1
Alle Antworten lösen einen Reflow aus, sodass es sich möglicherweise um einen Flaschenhals handelt. Wenn dies unterstützt wird , rufen Sie bitte IntersectionObserver . Es wird eine bessere Leistung auf modernen Browsern haben,
jcubic

Antworten:

1258

Dies sollte den Trick tun:

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

Einfache Dienstprogrammfunktion Mit dieser Funktion können Sie eine Dienstprogrammfunktion aufrufen, die das gesuchte Element akzeptiert und wenn das Element vollständig oder teilweise angezeigt werden soll.

function Utils() {

}

Utils.prototype = {
    constructor: Utils,
    isElementInView: function (element, fullyInView) {
        var pageTop = $(window).scrollTop();
        var pageBottom = pageTop + $(window).height();
        var elementTop = $(element).offset().top;
        var elementBottom = elementTop + $(element).height();

        if (fullyInView === true) {
            return ((pageTop < elementTop) && (pageBottom > elementBottom));
        } else {
            return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
        }
    }
};

var Utils = new Utils();

Verwendungszweck

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}
Scott Dowding
quelle
52
Beachten Sie, dass dies nur funktioniert, wenn das Dokument das gescrollte Element ist, dh Sie überprüfen nicht die Sichtbarkeit eines Elements in einem inneren Bildlaufbereich.
Andrew B.
8
Wie füge ich einen kleinen Versatz hinzu?
Jürgen Paul
5
Funktionierte nur, wenn ich window.innerHeightstattdessen benutzte
Christian Schnorr
2
Denn elemTopich habe benutzt $(elem).position().topund für elemBottomich habe benutzt elemTop + $(elem).outerHeight(true).
Sarah Vessels
13
Für: "Jeder Teil des Elements in der Ansicht" habe ich verwendet: (((elemTop> = docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom> = docViewTop) && (elemBottom <= docViewBottom)))
Grizly
415

Diese Antwort in Vanille:

function isScrolledIntoView(el) {
    var rect = el.getBoundingClientRect();
    var elemTop = rect.top;
    var elemBottom = rect.bottom;

    // Only completely visible elements return true:
    var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
    // Partially visible elements return true:
    //isVisible = elemTop < window.innerHeight && elemBottom >= 0;
    return isVisible;
}
Bravedick
quelle
27
sollte nicht das isVisible = elementTop < window.innerHeight && elementBottom >= 0? Andernfalls gibt eine Elementhälfte auf dem Bildschirm false zurück.
Gman
7
Nein. Ich überprüfe, ob ein Element auf der Seite vollständig sichtbar ist. Wenn Sie die Sichtbarkeit eines Teils überprüfen möchten, können Sie dieses Snippet anpassen.
Bravedick
15
Ich finde, dass diese Antwort besser abschneidet als die gewählte Antwort. Einfacher auch.
Adam Venezia
12
Im Vergleich zur genehmigten Antwort ist dies mit Hunderten von Elementen viel besser.
Ncla
5
Sehen Sie eine kleine Geige, die hier demonstriert - jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud
122

Update: Verwenden Sie IntersectionObserver


Die beste Methode, die ich bisher gefunden habe, ist das jQuery-Plugin . Klappt wunderbar.

Imitiert ein benutzerdefiniertes "Erscheinen" -Ereignis, das ausgelöst wird, wenn ein Element in die Ansicht gescrollt oder auf andere Weise für den Benutzer sichtbar wird.

$('#foo').appear(function() {
  $(this).text('Hello world');
});

Dieses Plugin kann verwendet werden, um unnötige Anfragen nach Inhalten zu vermeiden, die versteckt oder außerhalb des sichtbaren Bereichs liegen.

Joe Lencioni
quelle
30
Dies ist zweifellos ein cooles Plugin, beantwortet aber die Frage nicht.
Jon Adams
5
Während das jQuery-erscheinende Plugin für Inhalte im Hauptseitenbereich geeignet ist, gibt es leider Probleme mit Scroll-Divs mit fester Größe und Überlauf. Das Ereignis kann vorzeitig ausgelöst werden, wenn sich das gebundene Element innerhalb des sichtbaren Bereichs der Seite, aber außerhalb des sichtbaren Bereichs des Div befindet, und dann nicht wie erwartet ausgelöst werden, wenn das Element im div angezeigt wird.
Peter
17
Gibt es ein Plugin zum Verschwinden?
Shamoon
3
@Shamoon Überprüfen Sie die Quelle für die appear pluginund Sie müssen wahrscheinlich nur !irgendwo hinzufügen , um ein disappearPlugin zu bekommen .
Lucky Soni
5
Hinweis: Dies funktioniert nicht mit jQuery 1.11.X github.com/morr/jquery.appear/issues/37
Jason Parham
86

Hier ist meine reine JavaScript-Lösung, die funktioniert, wenn sie auch in einem scrollbaren Container versteckt ist.

Demo hier (versuchen Sie auch die Größe des Fensters zu ändern)

var visibleY = function(el){
  var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
    el = el.parentNode
  // Check if bottom of the element is off the page
  if (rect.bottom < 0) return false
  // Check its within the document viewport
  if (top > document.documentElement.clientHeight) return false
  do {
    rect = el.getBoundingClientRect()
    if (top <= rect.bottom === false) return false
    // Check if the element is out of view due to a container scrolling
    if ((top + height) <= rect.top) return false
    el = el.parentNode
  } while (el != document.body)
  return true
};

EDIT 2016-03-26: Ich habe die Lösung aktualisiert, um das Scrollen am Element vorbei zu berücksichtigen, sodass es über dem oberen Rand des scrollbaren Containers verborgen ist. BEARBEITEN 2018-10-08: Aktualisiert, um zu handhaben, wenn über dem Bildschirm aus der Ansicht gescrollt wird.

Verbündete
quelle
danke, vielleicht besser sein return top <= document.documentElement.clientHeight && top >= 0;
Yousef Salimpour
16
+1 Dies war die einzige codierte Antwort (dh keine Antwort von Drittanbietern), die den rekursiven Charakter von Elementen berücksichtigt. Ich habe erweitert, um horizontale, vertikale und Seitenlauf zu behandeln: jsfiddle.net/9nuqpgqa
Pebbl
3
Diese Lösung überprüft nur die Oberseite des Elements. Wenn das erste obere Pixel sichtbar ist, wird true zurückgegeben, auch wenn der Rest des Elements nicht sichtbar ist. Um zu überprüfen, ob das gesamte Element sichtbar ist, müssen Sie auch die Eigenschaft bottom überprüfen.
Wojciech Jakubas
2
Ja, ordentlich! Wird verwendet, um diese Antwort zu schreiben (mit Gutschrift als js Kommentar).
Roamer-1888
Vermisst; nach dem zweiten "return false" in der Schleife
Mikhail Ramendik
45

Verwenden der IntersectionObserver- API (nativ in modernen Browsern)

Mithilfe eines Beobachters können Sie einfach und effizient feststellen, ob ein Element im Ansichtsfenster oder in einem scrollbaren Container sichtbar ist .

Das Anhängen eines scrollEreignisses und das manuelle Überprüfen des Ereignisrückrufs entfällt, sodass die Effizienz entfällt:

// this is the target which is observed
var target = document.querySelector('div');

// configure the intersection observer instance
var intersectionObserverOptions = {
  root: null,
  rootMargin: '150px',
  threshold: 1.0
}
    
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);

// provide the observer with a target
observer.observe(target);

function onIntersection(entries){
  entries.forEach(entry => {
    console.clear();
    console.log(entry.intersectionRatio)
    target.classList.toggle('visible', entry.intersectionRatio > 0);
    
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {
      // Stop watching 
      // observer.unobserve(entry.target);
    }
  });
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class='box'></div>


Unterstützungstabelle für Browser anzeigen (in IE / Safari nicht unterstützt)

vsync
quelle
4
Vielen Dank! Dies funktioniert für mich und hat es auch in IE11 mit github.com/w3c/IntersectionObserver
Matt Wilson
Mit Abstand die beste Lösung. Arbeitete in IE11 ohne Polyfill!
Fabian von Ellerts
Beachten Sie, dass dies in iOS / macOS Safari leider NOCH nicht unterstützt wird. Stellen Sie sicher, dass Sie die Perf-Probleme überprüfen, wenn Sie sich für Polyfill entscheiden. Das ist eine große Gruppe von Benutzern
Leland,
@Leland - es ist projektabhängig. Für alle meine Projekte ist dies eine absolute 0-Benutzergruppe. Ich baue keine Websites, sondern ein Web-System;)
vsync
Ich versuche, dies in einer Schleife auf mehreren Elementen auszuführen, aber es funktioniert nicht. Irgendwelche Ideen? Ich füge das Element zum Ziel in dieser Schleife hinzu.
Sascha Grindau
42

Das jQuery Waypoints Plugin funktioniert hier sehr gut.

$('.entry').waypoint(function() {
   alert('You have scrolled to an entry.');
});

Es gibt einige Beispiele auf der Seite des Plugins .

Fedir RYKHTIK
quelle
3
Für mich funktionierte es nur mit einem Offset $('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' });
Leymannx
21

Wie wäre es mit

function isInView(elem){
   return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}

Danach können Sie auslösen, was Sie wollen, sobald das Element so angezeigt wird

$(window).scroll(function(){
   if (isInView($('.classOfDivToCheck')))
      //fire whatever you what 
      dothis();
})

Das funktioniert bei mir ganz gut

webicy
quelle
1
Dies funktioniert für mich, aber ich habe die scheinbar vollständigere Funktion isScrolledIntoView unter stackoverflow.com/questions/487073/… verwendet :)
Meetai.com
3
Ich denke, es sollte $ (window) .scrollTop () <$ (elem) .offset (). Top + $ (elem) .height () sein;
Junge
Meine Änderung würde folgendermaßen aussehen: `return $ (Fenster) .scrollTop () + $ (Fenster) .height ()> $ (elem) .offset (). Top + $ (elem) .height (); `
Bubencode
15

WebResourcesDepot hat vor einiger Zeit ein Skript zum Laden beim Scrollen geschrieben , das jQuery verwendet . Sie können ihre Live-Demo hier ansehen . Das Rindfleisch ihrer Funktionalität war folgendes:

$(window).scroll(function(){
  if  ($(window).scrollTop() == $(document).height() - $(window).height()){
    lastAddedLiveFunc();
  }
});

function lastAddedLiveFunc() { 
  $('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
  $.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
    function(data){
        if (data != "") {
          $(".wrdLatest:last").after(data);         
        }
      $('div#lastPostsLoader').empty();
    });
};
Sampson
quelle
15

Tweeked Scott Dowding's coole Funktion für meine Anforderung - diese wird verwendet, um herauszufinden, ob das Element gerade in den Bildschirm gescrollt hat, dh seine Oberkante.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
Snigdha Batra
quelle
12

Einfache Vanille, um zu überprüfen, ob element ( el) in scrollbarem div ( holder) sichtbar ist

function isElementVisible (el, holder) {
  holder = holder || document.body
  const { top, bottom, height } = el.getBoundingClientRect()
  const holderRect = holder.getBoundingClientRect()

  return top <= holderRect.top
    ? holderRect.top - top <= height
    : bottom - holderRect.bottom <= height
},

Verwendung mit jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);
Denis Matafonov
quelle
2
In dieser Ära der Einzelseitenanwendungen ist es üblicher geworden, zu überprüfen, ob ein Element in einem anderen Element als dem Fenster sichtbar ist . Deshalb bekommt dieser meine Gegenstimme.
H Hund
8

isScrolledIntoView ist eine sehr notwendige Funktion, daher habe ich sie ausprobiert. Sie funktioniert für Elemente, die nicht höher als das Ansichtsfenster sind. Wenn das Element jedoch größer als das Ansichtsfenster ist, funktioniert es nicht. Um dies zu beheben, ändern Sie einfach den Zustand

return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

dazu:

return (docViewBottom >= elemTop && docViewTop <= elemBottom);

Siehe Demo hier: http://jsfiddle.net/RRSmQ/

Robert
quelle
8

Die meisten Antworten hier berücksichtigen nicht, dass ein Element auch ausgeblendet werden kann, da es nicht nur für die gesamte Seite, sondern auch für ein Div gescrollt wird.

Um diese Möglichkeit abzudecken, müssen Sie grundsätzlich überprüfen, ob das Element innerhalb der Grenzen der einzelnen übergeordneten Elemente positioniert ist.

Diese Lösung macht genau das:

function(element, percentX, percentY){
    var tolerance = 0.01;   //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
    if(percentX == null){
        percentX = 100;
    }
    if(percentY == null){
        percentY = 100;
    }

    var elementRect = element.getBoundingClientRect();
    var parentRects = [];

    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;
};

Außerdem können Sie festlegen, zu welchem ​​Prozentsatz es in jeder Richtung sichtbar sein muss.
Es wird nicht die Möglichkeit abgedeckt, dass es aufgrund anderer Faktoren, wie z display: hidden.

Dies sollte in allen gängigen Browsern funktionieren, da es nur verwendet wird getBoundingClientRect. Ich habe es persönlich in Chrome und Internet Explorer 11 getestet.

Domysee
quelle
Vielen Dank für diesen Code. Ich frage mich, wie Sie den Ereignis-Listener beim Scrollen hinzufügen würden, wenn Sie mehrere verschachtelte scrollbare Elemente haben. Es scheint, als würde das Hinzufügen des Listeners zum Fenster allein nicht ausreichen. Müssen wir zum obersten übergeordneten Element zurückkehren, um den Listener zu jedem scrollbaren Container hinzuzufügen?
mr1031011
@ mr1031011 Es sollte möglich sein, den Handler zum Fenster hinzuzufügen und dann nach dem Ziel zu suchen, um den Container zu identifizieren, der gescrollt wurde.
Domysee
Richtig, es funktioniert nicht mit dem Beispiel von @vanowm,
mr1031011
7
function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop(),
        docViewBottom = docViewTop + $(window).height(),
        elemTop = $(elem).offset().top,
     elemBottom = elemTop + $(elem).height();
   //Is more than half of the element visible
   return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}
Pascal Gagneur
quelle
7

Hier ist eine weitere Lösung von http://web-profile.com.ua/

<script type="text/javascript">
$.fn.is_on_screen = function(){
    var win = $(window);
    var viewport = {
        top : win.scrollTop(),
        left : win.scrollLeft()
    };
    viewport.right = viewport.left + win.width();
    viewport.bottom = viewport.top + win.height();

    var bounds = this.offset();
    bounds.right = bounds.left + this.outerWidth();
    bounds.bottom = bounds.top + this.outerHeight();

    return (!(viewport.right < bounds.left || viewport.left > bounds.right ||    viewport.bottom < bounds.top || viewport.top > bounds.bottom));
 };

if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info       
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
$(window).scroll(function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
});
</script>

Sehen Sie es in JSFiddle

Adrian P.
quelle
7

Dies berücksichtigt alle Auffüllungen, Ränder oder Ränder des Elements sowie Elemente, die größer als das Ansichtsfenster selbst sind.

function inViewport($ele) {
    var lBound = $(window).scrollTop(),
        uBound = lBound + $(window).height(),
        top = $ele.offset().top,
        bottom = top + $ele.outerHeight(true);

    return (top > lBound && top < uBound)
        || (bottom > lBound && bottom < uBound)
        || (lBound >= top && lBound <= bottom)
        || (uBound >= top && uBound <= bottom);
}

Um es zu nennen, verwenden Sie so etwas:

var $myElement = $('#my-element'),
    canUserSeeIt = inViewport($myElement);

console.log(canUserSeeIt); // true, if element is visible; false otherwise
Brent Barbata
quelle
7

Für jQuery gibt es ein Plugin namens inview, das ein neues "inview" -Ereignis hinzufügt.


Hier ist ein Code für ein jQuery-Plugin, das keine Ereignisse verwendet:

$.extend($.expr[':'],{
    inView: function(a) {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
            ot = $(a).offset().top,
            wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
        return ot > st && ($(a).height() + ot) < (st + wh);
    }
});

(function( $ ) {
    $.fn.inView = function() {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
        ot = $(this).offset().top,
        wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();

        return ot > st && ($(this).height() + ot) < (st + wh);
    };
})( jQuery );

Ich fand dies in einem Kommentar hier ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) von einem Kerl namens James

ness-EE
quelle
Leider wird die jQuery-Ansicht nicht mehr verwaltet und funktioniert nicht mit aktuellen Versionen von jQuery.
Mikemaccana
1
JQuery 1 ist für die Unterstützung
älterer
Der Link zeigt das Beispiel nicht an, da die Seite aktualisiert wurde.
Professor für Programmierung
6

Ich musste die Sichtbarkeit von Elementen im scrollbaren DIV-Container überprüfen

    //p = DIV container scrollable
    //e = element
    function visible_in_container(p, e) {
        var z = p.getBoundingClientRect();
        var r = e.getBoundingClientRect();

        // Check style visiblilty and off-limits
        return e.style.opacity > 0 && e.style.display !== 'none' &&
               e.style.visibility !== 'hidden' &&
               !(r.top > z.bottom || r.bottom < z.top ||
                 r.left > z.right || r.right < z.left);
    }
Pigmalión
quelle
Dies funktioniert für mich, wenn ich das in ändere e.style.opacity > 0, (!e.style.opacity || e.style.opacity > 0)da es standardmäßig die leere Zeichenfolge für mich in FF ist.
Brett Zamir
6

Aufbauend auf dieser großartigen Antwort können Sie sie mit ES2015 + ein wenig weiter vereinfachen:

function isScrolledIntoView(el) {
  const { top, bottom } = el.getBoundingClientRect()
  return top >= 0 && bottom <= window.innerHeight
}

Wenn Sie sich nicht darum kümmern, dass die Oberseite aus dem Fenster geht, und nur darum, dass die Unterseite angezeigt wird, kann dies vereinfacht werden

function isSeen(el) {
  return el.getBoundingClientRect().bottom <= window.innerHeight
}

oder sogar der Einzeiler

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight
rpearce
quelle
4

Sie können das jquery-Plugin "onScreen" verwenden, um zu überprüfen, ob sich das Element beim Scrollen im aktuellen Ansichtsfenster befindet. Das Plugin setzt das ": onScreen" des Selektors auf true, wenn der Selektor auf dem Bildschirm angezeigt wird. Dies ist der Link für das Plugin, das Sie in Ihr Projekt aufnehmen können. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "

Sie können das folgende Beispiel ausprobieren, das für mich funktioniert.

$(document).scroll(function() {
    if($("#div2").is(':onScreen')) {
        console.log("Element appeared on Screen");
        //do all your stuffs here when element is visible.
    }
    else {
        console.log("Element not on Screen");
        //do all your stuffs here when element is not visible.
    }
});

HTML Quelltext:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>

CSS:

#div1 {
    background-color: red;
}
#div2 {
    background-color: green;
}
Vasuki Dileep
quelle
3

Ich habe eine solche Methode in meiner Anwendung, aber sie verwendet jQuery nicht:

/* Get the TOP position of a given element. */
function getPositionTop(element){
    var offset = 0;
    while(element) {
        offset += element["offsetTop"];
        element = element.offsetParent;
    }
    return offset;
}

/* Is a given element is visible or not? */
function isElementVisible(eltId) {
    var elt = document.getElementById(eltId);
    if (!elt) {
        // Element not found.
        return false;
    }
    // Get the top and bottom position of the given element.
    var posTop = getPositionTop(elt);
    var posBottom = posTop + elt.offsetHeight;
    // Get the top and bottom position of the *visible* part of the window.
    var visibleTop = document.body.scrollTop;
    var visibleBottom = visibleTop + document.documentElement.offsetHeight;
    return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}

Bearbeiten: Diese Methode funktioniert gut für IE (mindestens Version 6). Lesen Sie die Kommentare zur Kompatibilität mit FF.

Romain Linsolas
quelle
2
Aus irgendeinem Grund gibt document.body.scrollTop immer 0 zurück (auf ff3). Ändern Sie es in var visibleTop = (document.documentElement.scrollTop? Document.documentElement.scrollTop: document.body.scrollTop);
Yoavf
Das tut mir leid. Meine Anwendung darf nur in IE 6 ausgeführt werden (ja, ich habe kein Glück :(), daher habe ich dies nie in FF getestet ...
Romain Linsolas
Dies wäre hier die beste Antwort, wenn es richtig wäre. Korrigieren Sie eine Ihrer Zeilen: var visibleBottom = visibleTop + window.innerHeight;Ich verwende jQuery nicht und Sie haben mir geholfen, die richtige Antwort zu finden.
Bitterblue
3

Wenn Sie dies für das Scrollen eines Elements in einem anderen Div optimieren möchten,

function isScrolledIntoView (elem, divID) 

{

    var docViewTop = $('#' + divID).scrollTop();


    var docViewBottom = docViewTop + $('#' + divID).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 
}
Samiya Akhtar
quelle
3

Die akzeptierte Antwort wurde so geändert, dass für das Element die Anzeigeeigenschaft auf etwas anderes als "keine" festgelegt werden muss, damit die Qualität sichtbar wird.

function isScrolledIntoView(elem) {
   var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();
  var elemDisplayNotNone = $(elem).css("display") !== "none";

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}
evanmcd
quelle
3

Hier ist eine Möglichkeit, mit Mootools dasselbe zu erreichen, horizontal, vertikal oder beides.

Element.implement({
inVerticalView: function (full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewTop = windowScroll.y;
    var docViewBottom = docViewTop + windowSize.y;
    var elemTop = elementPosition.y;
    var elemBottom = elemTop + elementSize.y;

    if (full) {
        return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
            && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
    } else {
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }
},
inHorizontalView: function(full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewLeft = windowScroll.x;
    var docViewRight = docViewLeft + windowSize.x;
    var elemLeft = elementPosition.x;
    var elemRight = elemLeft + elementSize.x;

    if (full) {
        return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
            && (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
    } else {
        return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
    }
},
inView: function(full) {
    return this.inHorizontalView(full) && this.inVerticalView(full);
}});
bmlkc
quelle
3

Ein Beispiel basierend auf dieser Antwort , um zu überprüfen, ob ein Element zu 75% sichtbar ist (dh weniger als 25% davon sind außerhalb des Bildschirms).

function isScrolledIntoView(el) {
  // check for 75% visible
  var percentVisible = 0.75;
  var elemTop = el.getBoundingClientRect().top;
  var elemBottom = el.getBoundingClientRect().bottom;
  var elemHeight = el.getBoundingClientRect().height;
  var overhang = elemHeight * (1 - percentVisible);

  var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
  return isVisible;
}
Brendan Nee
quelle
3

Es gibt über 30 Antworten auf diese Frage, und keine von ihnen verwendet die erstaunlich einfache, reine JS-Lösung, die ich verwendet habe. Es ist nicht erforderlich, jQuery zu laden, um dies zu lösen, da viele andere darauf drängen.

Um festzustellen, ob sich das Element im Ansichtsfenster befindet, müssen wir zuerst die Position der Elemente innerhalb des Körpers bestimmen. Wir müssen dies nicht rekursiv tun, wie ich einmal dachte. Stattdessen können wir verwenden element.getBoundingClientRect().

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

Dieser Wert ist die Y-Differenz zwischen der Oberseite des Objekts und der Oberseite des Körpers.

Wir müssen dann feststellen, ob das Element in Sichtweite ist. Bei den meisten Implementierungen wird gefragt, ob sich das vollständige Element im Ansichtsfenster befindet. Daher werden wir dies behandeln.

Zuallererst ist die oberste Position des Fensters: window.scrollY .

Wir können die untere Position des Fensters ermitteln, indem wir die Höhe des Fensters zu seiner oberen Position hinzufügen:

var window_bottom_position = window.scrollY + window.innerHeight;

Erstellen Sie eine einfache Funktion, um die oberste Position des Elements zu ermitteln:

function getElementWindowTop(elem){
    return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

Diese Funktion gibt die oberste Position des Elements innerhalb des Fensters zurück oder sie wird zurückgegeben, 0wenn Sie etwas anderes als ein Element mit dem übergeben.getBoundingClientRect() Methode . Diese Methode gibt es schon lange, daher sollten Sie sich keine Sorgen machen müssen, dass Ihr Browser sie nicht unterstützt.

Die oberste Position unseres Elements ist nun:

var element_top_position = getElementWindowTop(element);

Die untere Position des Elements ist:

var element_bottom_position = element_top_position + element.clientHeight;

Jetzt können wir feststellen, ob sich das Element im Ansichtsfenster befindet, indem wir überprüfen, ob die untere Position des Elements niedriger als die obere Position des Ansichtsfensters ist und ob die obere Position des Elements höher als die untere Position des Ansichtsfensters ist:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
    //element is in view
else
    //element is not in view

Von dort aus können Sie die Logik ausführen, um eine in-viewKlasse zu Ihrem Element hinzuzufügen oder zu entfernen , die Sie später mit Übergangseffekten in Ihrem CSS behandeln können.

Ich bin absolut erstaunt, dass ich diese Lösung nirgendwo anders gefunden habe, aber ich glaube, dass dies die sauberste und effektivste Lösung ist und dass Sie jQuery nicht laden müssen!

WebWanderer
quelle
Sehr schöne Erklärung! Aber es gibt bereits Antworten, die genau das tun, was Sie tun, wie Allys Antwort
Domysee
1
@Domysee Hmm, das habe ich irgendwie übersprungen. Meinetwegen. Vielen Dank, dass Sie darauf hingewiesen haben. Es ist schön zu sehen, dass dies anders gemacht wird.
WebWanderer
3

Eine effizientere Version dieser Antwort :

 /**
 * Is element within visible region of a scrollable container
 * @param {HTMLElement} el - element to test
 * @returns {boolean} true if within visible region, otherwise false
 */
 function isScrolledIntoView(el) {
      var rect = el.getBoundingClientRect();
      return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
 }
John Doherty
quelle
2

Diese Methode gibt true zurück, wenn ein Teil des Elements auf der Seite sichtbar ist. In meinem Fall hat es besser funktioniert und kann jemand anderem helfen.

function isOnScreen(element) {
  var elementOffsetTop = element.offset().top;
  var elementHeight = element.height();

  var screenScrollTop = $(window).scrollTop();
  var screenHeight = $(window).height();

  var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
  var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;

  return scrollIsAboveElement && elementIsVisibleOnScreen;
}
Rafael Garcia
quelle
2

Einfache Änderung für scrollbares Div (Container)

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

HINWEIS: Dies funktioniert nicht, wenn das Element größer als das scrollbare div ist.

Derrick J Wippler
quelle
2

Ich habe diese kurze jQuery-Funktionserweiterung angepasst, die Sie gerne verwenden können (MIT-Lizenz).

/**
 * returns true if an element is visible, with decent performance
 * @param [scope] scope of the render-window instance; default: window
 * @returns {boolean}
 */
jQuery.fn.isOnScreen = function(scope){
    var element = this;
    if(!element){
        return;
    }
    var target = $(element);
    if(target.is(':visible') == false){
        return false;
    }
    scope = $(scope || window);
    var top = scope.scrollTop();
    var bot = top + scope.height();
    var elTop = target.offset().top;
    var elBot = elTop + target.height();

    return ((elBot <= bot) && (elTop >= top));
};
Lorenz Lo Sauer
quelle
2

Ich habe eine Komponente für diese Aufgabe geschrieben, die darauf ausgelegt ist, eine große Anzahl von Elementen extrem schnell zu verarbeiten (mit einer Geschwindigkeit von <10 ms für 1000 Elemente auf einem langsamen Mobiltelefon) ).

Es arbeitet mit jeder Art von Scroll - Container haben Sie Zugriff auf - Fenster, HTML - Elemente, eingebettet iframe, gelaicht Kind Fenster - und ist sehr flexibel, was es erkennt ( vollständige oder teilweise Sichtbarkeit , Grenzfeld oder Content - Box , individuelle Toleranzzone , usw. ).

Eine riesige, meist automatisch generierte Testsuite stellt sicher, dass sie wie angekündigt und browserübergreifend funktioniert .

Probieren Sie es aus, wenn Sie möchten : jQuery.isInView . Andernfalls finden Sie möglicherweise Inspiration im Quellcode, z . B. hier .

Hashwechsel
quelle