example - javascript tutorial




Controlla se l'elemento è visibile dopo lo scorrimento (20)

È possibile utilizzare il plugin jQuery "onScreen" per verificare se l'elemento si trova nella finestra corrente quando si scorre. Il plugin imposta su ": onScreen" del selettore su true quando il selettore appare sullo schermo. Questo è il link per il plugin che puoi includere nel tuo progetto. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "

Puoi provare l'esempio seguente che funziona per me.

$(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.
    }
});

Codice HTML:

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

Sto caricando elementi tramite AJAX. Alcuni di questi sono visibili solo se scorri la pagina verso il basso.
C'è un modo per sapere se un elemento si trova ora nella parte visibile della pagina?


Avevo bisogno di controllare la visibilità degli elementi all'interno del contenitore DIV scorrevole

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

Che ne dite di

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

Dopodiché puoi attivare quello che vuoi quando l'elemento è in vista in questo modo

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

Questo funziona per me bene


Ecco la mia soluzione JavaScript pura che funziona anche se è nascosta all'interno di un contenitore scorrevole.

Demo qui (prova a ridimensionare anche la finestra)

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 26/03/2016: Ho aggiornato la soluzione per tenere conto dello scorrimento oltre l'elemento in modo che sia nascosto sopra la parte superiore del contenitore in grado di scorrere. EDIT 2018-10-08: aggiornato da gestire quando si scorre fuori dalla vista sopra lo schermo.


Ecco un'altra soluzione da 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>

JSFiddle in JSFiddle


Ho adattato questa breve estensione della funzione jQuery, che puoi usare liberamente (licenza MIT).

/**
 * 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));
};

Ho un tale metodo nella mia applicazione, ma non usa jQuery:

/* 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));
}

Modifica: questo metodo funziona bene per IE (almeno la versione 6). Leggi i commenti per compatibilità con FF.


Il miglior metodo che ho trovato finora è il plugin jQuery . Funziona come un fascino.

Imita un evento "compare" personalizzato, che si attiva quando un elemento scorre in vista o diventa altrimenti visibile all'utente.

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

Questo plug-in può essere utilizzato per evitare richieste non necessarie di contenuti nascosti o al di fuori dell'area visibile.


La fantastica funzione di Tweeked Scott Dowding per il mio requisito - questa viene usata per scoprire se l'elemento è appena passato nello schermo cioè è il bordo superiore.

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

La maggior parte delle risposte qui non tiene conto del fatto che un elemento può anche essere nascosto perché viene fatto scorrere fuori dalla vista di un div, non solo dell'intera pagina.

Per coprire questa possibilità, devi fondamentalmente controllare se l'elemento è posizionato all'interno dei limiti di ciascuno dei suoi genitori.

Questa soluzione fa esattamente questo:

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

Permette anche di specificare a quale percentuale deve essere visibile in ogni direzione.
Non copre la possibilità che possa essere nascosto a causa di altri fattori, come la display: hidden .

Questo dovrebbe funzionare in tutti i principali browser, poiché utilizza solo getBoundingClientRect . L'ho testato personalmente su Chrome e Internet Explorer 11.


Partendo da questa grande risposta , puoi semplificarla un po 'usando ES2015 +:

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

Se non ti interessa che la parte superiore esca dalla finestra e ti interessi che il fondo sia stato visualizzato, questo può essere semplificato

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

o anche l'una-linea

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

Plain vanilla per verificare se l'elemento ( el ) è visibile nel div scorrevole ( holder )

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

Utilizzo con jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);

Questo considera ogni padding, border o margin che l'elemento ha così come elementi più grandi della viewport stessa.

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

Per chiamarlo usa qualcosa del genere:

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

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

Questo dovrebbe fare il trucco:

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

Funzione di utilità semplice Questo ti permetterà di chiamare una funzione di utilità che accetta l'elemento che stai cercando e se vuoi che l'elemento sia completamente visibile o parzialmente.

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();

uso

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

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}

Se si desidera modificare questo elemento per lo scorrimento all'interno di un altro div,

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

Semplice modifica per div scorrevole (contenitore)

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

NOTA: questo non funziona se l'elemento è più grande del div scorrevole.


Un esempio basato su questa risposta per verificare se un elemento è visibile al 75% (cioè meno del 25% di esso è fuori dallo schermo).

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

Utilizzando la nuova API IntersectionObserver è molto semplice ed efficiente determinare se un elemento è visibile nel viewport. Utilizzando un osservatore , elimina la necessità di allegare un evento di scroll e controllare manualmente la richiamata dell'evento.

// 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);

// provice 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>

Visualizza la tabella di supporto dei browser (non supportata in IE / Safari)


isScrolledIntoView è una funzione molto utile, quindi l'ho provata, funziona per elementi non più pesanti del viewport, ma se l'elemento è più grande come il viewport non funziona. Per risolvere questo facilmente cambiare la condizione

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

a questo:

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

Vedi la demo qui: http://jsfiddle.net/RRSmQ/


Questa risposta in Vanilla:

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






scroll