web-dev-qa-db-fra.com

Faire défiler si l'élément n'est pas visible

comment déterminer, à l'aide de jquery, si l'élément est visible dans la vue en cours. J'aimerais ajouter une fonctionnalité de commentaire, qui fonctionne comme dans Facebook, où vous ne faites défiler que l'élément si ce n'est pas visible. Par visible, je veux dire que ce n'est pas dans la vue en cours, mais vous pouvez faire défiler jusqu'à l'élément.

19
macpak

Démo en direct

En gros, il vous suffit de vérifier la position de l'élément pour voir s'il se trouve dans la fenêtre d'affichage.

function checkIfInView(element){
    var offset = element.offset().top - $(window).scrollTop();

    if(offset > window.innerHeight){
        // Not in view so scroll to it
        $('html,body').animate({scrollTop: offset}, 1000);
        return false;
    }
   return true;
}
36
Loktar

Améliorer la réponse de Loktar, en corrigeant ce qui suit:

  1. Faire défiler
  2. Faites défiler jusqu'à un affichage: aucun élément (comme les div cachés, etc.)

    function scrollToView(element){
        var offset = element.offset().top;
        if(!element.is(":visible")) {
            element.css({"visibility":"hidden"}).show();
            var offset = element.offset().top;
            element.css({"visibility":"", "display":""});
        }
    
        var visible_area_start = $(window).scrollTop();
        var visible_area_end = visible_area_start + window.innerHeight;
    
        if(offset < visible_area_start || offset > visible_area_end){
             // Not in view so scroll to it
             $('html,body').animate({scrollTop: offset - window.innerHeight/3}, 1000);
             return false;
        }
        return true;
    }
    
11
digitalPBK

Après avoir essayé toutes ces solutions et bien d’autres encore, aucune d’entre elles ne répondait à mon besoin d’exécuter un vieux logiciel de portail Web (âgé de 10 ans) dans IE11 (dans certains modes de compatibilité). Ils ont tous échoué à déterminer correctement si l'élément était visible. Cependant j'ai trouvé cette solution . J'espère que ça aide.

function scrollIntoViewIfOutOfView(el) {
    var topOfPage = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    var heightOfPage = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    var elY = 0;
    var elH = 0;
    if (document.layers) { // NS4
        elY = el.y;
        elH = el.height;
    }
    else {
        for(var p=el; p&&p.tagName!='BODY'; p=p.offsetParent){
            elY += p.offsetTop;
        }
        elH = el.offsetHeight;
    }
    if ((topOfPage + heightOfPage) < (elY + elH)) {
        el.scrollIntoView(false);
    }
    else if (elY < topOfPage) {
        el.scrollIntoView(true);
    }
}
5
user1806949

J'ai créé une version légèrement plus générique de la réponse de digitalPBK qui fait défiler de manière minimale un élément contenu dans un div ou un autre conteneur (y compris le corps). Vous pouvez transmettre des éléments DOM ou des sélecteurs à la fonction, à condition que l'élément soit contenu dans le parent.

function scrollToView(element, parent) {
    element = $(element);
    parent = $(parent);

    var offset = element.offset().top + parent.scrollTop();

    var height = element.innerHeight();
    var offset_end = offset + height;
    if (!element.is(":visible")) {
        element.css({"visibility":"hidden"}).show();
        var offset = element.offset().top;
        element.css({"visibility":"", "display":""});
    }

    var visible_area_start = parent.scrollTop();
    var visible_area_end = visible_area_start + parent.innerHeight();

    if (offset-height < visible_area_start) {
        parent.animate({scrollTop: offset-height}, 600);
        return false;
    } else if (offset_end > visible_area_end) {
        parent.animate({scrollTop: parent.scrollTop()+ offset_end - visible_area_end }, 600);
        return false;

    }
    return true;
}
5
jaggedcow

Vous pouvez jeter un coup d'œil à son super lien dans le livre de recettes jQuery:

Déterminer si un élément est dans la fenêtre

Test si Element est contenu dans la fenêtre

jQuery(document).ready(function() {
    var viewportWidth = jQuery(window).width(),
        viewportHeight = jQuery(window).height(),
        documentScrollTop = jQuery(document).scrollTop(),
        documentScrollLeft = jQuery(document).scrollLeft(),

        $myElement = jQuery('#myElement'),

        elementOffset = $myElement.offset(),
        elementHeight = $myElement.height(),
        elementWidth = $myElement.width(),

        minTop = documentScrollTop,
        maxTop = documentScrollTop + viewportHeight,
        minLeft = documentScrollLeft,
        maxLeft = documentScrollLeft + viewportWidth;

    if (
        (elementOffset.top > minTop && elementOffset.top + elementHeight < maxTop) &&
        (elementOffset.left > minLeft && elementOffset.left + elementWidth < maxLeft)
    ) {
        alert('entire element is visible');
    } else {
        alert('entire element is not visible');
    }
});

Test quelle quantité de l'élément est visible

jQuery(document).ready(function() {

var viewportWidth = jQuery(window).width(),
    viewportHeight = jQuery(window).height(),

    documentScrollTop = jQuery(document).scrollTop(),
    documentScrollLeft = jQuery(document).scrollLeft(),

    $myElement = jQuery('#myElement'),

    verticalVisible, horizontalVisible,

    elementOffset = $myElement.offset(),
    elementHeight = $myElement.height(),
    elementWidth = $myElement.width(),

    minTop = documentScrollTop,
    maxTop = documentScrollTop + viewportHeight,
    minLeft = documentScrollLeft,
    maxLeft = documentScrollLeft + viewportWidth;

function scrollToPosition(position) {
    jQuery('html,body').animate({
        scrollTop : position.top,
        scrollLeft : position.left
    }, 300);
}

if (
    ((elementOffset.top > minTop && elementOffset.top < maxTop) ||
    (elementOffset.top + elementHeight > minTop && elementOffset.top + 
elementHeight < maxTop))
&&  ((elementOffset.left > minLeft && elementOffset.left < maxLeft) ||
    (elementOffset.left + elementWidth > minLeft && elementOffset.left +
elementWidth < maxLeft)))
{
    alert('some portion of the element is visible');

    if (elementOffset.top >= minTop && elementOffset.top + elementHeight 
<= maxTop) {
        verticalVisible = elementHeight;
    } else if (elementOffset.top < minTop) {
        verticalVisible = elementHeight - (minTop - elementOffset.top);
    } else {
        verticalVisible = maxTop - elementOffset.top;
    }

    if (elementOffset.left >= minLeft && elementOffset.left + elementWidth 
<= maxLeft) {
        horizontalVisible = elementWidth;
    } else if (elementOffset.left < minLeft) {
        horizontalVisible = elementWidth - (minLeft - elementOffset.left);
    } else {
        horizontalVisible = maxLeft - elementOffset.left;
    }

    var percentVerticalVisible = (verticalVisible / elementHeight) * 100;
    var percentHorizontalVisible = (horizontalVisible / elementWidth) * 100;

    if (percentVerticalVisible < 50 || percentHorizontalVisible < 50) {
        alert('less than 50% of element visible; scrolling');
        scrollToPosition(elementOffset);
    } else {
        alert('enough of the element is visible that there is no need to scroll');
    }

} else {
    // element is not visible; scroll to it
    alert('element is not visible; scrolling');
    scrollToPosition(elementOffset);
}
3
Leniel Maccaferri

Le code suivant m'a aidé à atteindre le résultat

function scroll_to_element_if_not_inside_view(element){
  if($(window).scrollTop() > element.offset().top){
    $('html, body').animate( { scrollTop: element.offset().top }, {duration: 400 } );
  }
}
1
Ashok Gj

Il existe un plugin jQuery qui nous permet de vérifier rapidement si un élément entier (ou seulement une partie) se trouve dans la fenêtre d'affichage visuelle du navigateur, quelle que soit la position de défilement de la fenêtre. Vous devez le télécharger depuis son dépôt GitHub :

Supposons avoir le code HTML suivant et que vous souhaitez alerter lorsque le pied de page est visible:

<section id="container">
    <aside id="sidebar">
        <p>
            Scroll up and down to alert the footer visibility by color:
        </p>
        <ul>
            <li><span class="blue">Blue</span> = footer <u>not visible</u>;</li>
            <li><span class="yellow">Yellow</span> = footer <u>visible</u>;</li>
        </ul>
        <span id="alert"></span>
    </aside>
    <section id="main_content"></section>
</section>
<footer id="page_footer"></footer>

Alors, ajoutez le plugin avant la fermeture de la balise body:

<script type="text/javascript" src="js/jquery-1.12.0.min.js"></script>
<script type="text/javascript" src="js/jquery_visible/examples/js/jq.visible.js"></script>

Après cela, vous pouvez l'utiliser d'une manière simple comme ceci:

<script type="text/javascript">
jQuery( document ).ready(function ( $ ) {
  if ($("footer#page_footer").visible(true, false, "both")) {
    $("#main_content").css({"background-color":"#ffeb3b"});
    $("span#alert").html("Footer visible");
  } else {
    $("#main_content").css({"background-color":"#4aafba"});
    $("span#alert").html("Footer not visible");
  }

  $(window).scroll(function() {
    if ($("footer#page_footer").visible(true, false, "both")) {
      $("#main_content").css({"background-color":"#ffeb3b"});
      $("span#alert").html("Footer visible");
    } else {
      $("#main_content").css({"background-color":"#4aafba"});
      $("span#alert").html("Footer not visible");
    }
  });
});
</script>

Voici un demo

0
Riccardo Volpe