web-dev-qa-db-fra.com

Vérifier si l'élément est visible à l'écran

Duplicate possible:
jQuery - Vérifie si l’élément est visible après scroling

J'essaie de déterminer si un élément est visible à l'écran. Pour cela, j'essaie de trouver la position verticale de l'élément en utilisant offsetTop, mais la valeur renvoyée n'est pas correcte. Dans ce cas, l'élément n'est visible que si vous faites défiler l'écran vers le bas. Malgré cela, offsetTop renvoie une valeur de 618 lorsque la hauteur de mon écran est de 703; ainsi, selon offsetTop, l'élément doit être visible.

Le code que j'utilise ressemble à ceci:

function posY(obj)
{
  var curtop = 0;

  if( obj.offsetParent )
  {
    while(1)
    {
      curtop += obj.offsetTop;

      if( !obj.offsetParent )
      {
        break;
      }

      obj = obj.offsetParent;
    }
  } else if( obj.y )
    {
     curtop += obj.y;
    }

  return curtop;
}

Merci d'avance!

62
Robert

Bien BenM a déclaré, vous devez détecter la hauteur de la fenêtre + la position de défilement pour correspondre à votre poisiton en haut. La fonction que vous utilisez est correcte et fait le travail, même si elle est un peu plus complexe.

Si vous n'utilisez pas jQuery, le script ressemblerait à ceci:

function posY(Elm) {
    var test = Elm, top = 0;

    while(!!test && test.tagName.toLowerCase() !== "body") {
        top += test.offsetTop;
        test = test.offsetParent;
    }

    return top;
}

function viewPortHeight() {
    var de = document.documentElement;

    if(!!window.innerWidth)
    { return window.innerHeight; }
    else if( de && !isNaN(de.clientHeight) )
    { return de.clientHeight; }

    return 0;
}

function scrollY() {
    if( window.pageYOffset ) { return window.pageYOffset; }
    return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
}

function checkvisible( Elm ) {
    var vpH = viewPortHeight(), // Viewport Height
        st = scrollY(), // Scroll Top
        y = posY(Elm);

    return (y > (vpH + st));
}

Utiliser jQuery est beaucoup plus facile:

function checkVisible( Elm, evalType ) {
    evalType = evalType || "visible";

    var vpH = $(window).height(), // Viewport Height
        st = $(window).scrollTop(), // Scroll Top
        y = $(Elm).offset().top,
        elementHeight = $(Elm).height();

    if (evalType === "visible") return ((y < (vpH + st)) && (y > (st - elementHeight)));
    if (evalType === "above") return ((y < (vpH + st)));
}

Cela offre même un deuxième paramètre. Avec "visible" (ou pas de second paramètre), il vérifie strictement si un élément est à l'écran. S'il est défini sur "au-dessus", il retournera la valeur true si l'élément en question se trouve sur ou au-dessus de l'écran.

Voir en action: http://jsfiddle.net/RJX5N/2/

J'espère que cela répond à votre question.

- VERSION AMÉLIORÉE -

C'est beaucoup plus court et devrait le faire aussi:

function checkVisible(Elm) {
  var rect = Elm.getBoundingClientRect();
  var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
  return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}

avec un violon pour le prouver: http://jsfiddle.net/t2L274ty/1/

Et une version avec threshold et mode inclus:

function checkVisible(Elm, threshold, mode) {
  threshold = threshold || 0;
  mode = mode || 'visible';

  var rect = Elm.getBoundingClientRect();
  var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
  var above = rect.bottom - threshold < 0;
  var below = rect.top - viewHeight + threshold >= 0;

  return mode === 'above' ? above : (mode === 'below' ? below : !above && !below);
}

et avec un violon pour le prouver: http://jsfiddle.net/t2L274ty/2/

114
Tokimon

Pourriez-vous utiliser jQuery, car compatible avec plusieurs navigateurs?

function isOnScreen(element)
{
    var curPos = element.offset();
    var curTop = curPos.top;
    var screenHeight = $(window).height();
    return (curTop > screenHeight) ? false : true;
}

Et appelez ensuite la fonction en utilisant quelque chose comme:

if(isOnScreen($('#myDivId'))) { /* Code here... */ };
16
BenM