web-dev-qa-db-fra.com

jQuery défiler jusqu'à l'ancre (moins la quantité de pixels définie)

J'utilise le code suivant pour faire défiler les points d'ancrage avec jQuery:

$(document).ready(function() {
  function filterPath(string) {
  return string
    .replace(/^\//,'')
    .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
    .replace(/\/$/,'');
  }
  var locationPath = filterPath(location.pathname);
  var scrollElem = scrollableElement('html', 'body');

  $('a[href*=#]').each(function() {
    var thisPath = filterPath(this.pathname) || locationPath;
    if (  locationPath == thisPath
    && (location.hostname == this.hostname || !this.hostname)
    && this.hash.replace(/#/,'') ) {
      var $target = $(this.hash), target = this.hash;
      if (target) {
        var targetOffset = $target.offset().top;
        $(this).click(function(event) {
          event.preventDefault();
          $(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
            location.hash = target;
          });
        });
      }
    }
  });

  // use the first element that is "scrollable"
  function scrollableElement(els) {
    for (var i = 0, argLength = arguments.length; i <argLength; i++) {
      var el = arguments[i],
          $scrollElement = $(el);
      if ($scrollElement.scrollTop()> 0) {
        return el;
      } else {
        $scrollElement.scrollTop(1);
        var isScrollable = $scrollElement.scrollTop()> 0;
        $scrollElement.scrollTop(0);
        if (isScrollable) {
          return el;
        }
      }
    }
    return [];
  }

});

Existe-t-il de toute façon de le faire défiler jusqu'à cette ancre, mais moins une quantité définie de pixels? (dans mon cas, je veux que ce soit -92px)

Merci pour toute aide.

30
John

Je devais juste résoudre ce problème moi-même. Vous devez ajuster votre décalage en fonction de la quantité de pixels que vous souhaitez faire défiler. Dans mon cas, j'avais besoin qu'il soit 50 pixels plus haut sur la page. J'ai donc soustrait 50 de targetOffset.

Maintenant, la partie du code qui vous fait vaciller est location.hash - cela indique au navigateur de définir son emplacement à un point spécifique. Dans tous les cas, il s'agit d'une chaîne contenant l'ID auquel vous venez de faire défiler. Donc, ce serait quelque chose comme '#foo'. Vous devez maintenir cela, nous allons donc le laisser.

Cependant, pour empêcher le navigateur de "sauter" lorsque location.hash est défini (une action par défaut du navigateur), vous devez simplement empêcher l'action par défaut. Donc, passez votre événement "e" à travers la fonction d'achèvement de la fonction d'animation. Appelez ensuite simplement e.preventDefault (). Vous devrez vous assurer que le navigateur appelle réellement un événement, sinon il se produira une erreur. Ainsi, un test if corrige cela.

Terminé. Voici le bloc de code révisé:

if (target) {
    var targetOffset = $target.offset().top - 50;
    $(this).click(function(event) {
      if(event != 'undefined') {
          event.preventDefault();}
      $(scrollElem).animate({scrollTop: targetOffset}, 400, function(e) {
          e.preventDefault();
          location.hash = target;
      });
    });
  }
31
Jonathan Savage

Voici ce que j'utilise:

function scrollToDiv(element){
    element = element.replace("link", "");
    $('html,body').unbind().animate({scrollTop: $(element).offset().top-50},'slow');
};

...où 50 est le nombre de pixels à ajouter/soustraire.

18
kaleazy

Ce code fonctionne pour moi dans n'importe quelle ancre de lien dans mon site, respectant la hauteur de "150 px" pour le menu fixe en haut.

<!-- SMOOTH SCROLL -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top-150
        }, 1000);
        return false;
      }
    }
  });
});
</script>
<!-- End of SMOOTH SCROLL -->
13
Max

Lol)

<span class="anchor" id="section1"></span>
<div class="section"></div>

<span class="anchor" id="section2"></span>
<div class="section"></div>

<span class="anchor" id="section3"></span>
<div class="section"></div>

<style>
.anchor{
  display: block;
  height: 115px; /*same height as header*/
  margin-top: -115px; /*same height as header*/
  visibility: hidden;
}
</style>

Je n'ai pas pu utiliser la solution de Jonathan Savage car je n'ai pas pu passer un rappel d'événement dans animate () sans erreur. J'ai eu ce problème aujourd'hui et j'ai trouvé une solution simple:

      var $target = $(this.hash), target = this.hash;
      if (target) {
        var targetOffset = $target.offset().top - 92;
        $(this).click(function(event) {
          event.preventDefault();
          $(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
            location.hash = targetOffset;
          });
        });

Soustrayez le décalage en pixels de la variable targetOffset, puis affectez location.hash à cette variable. Arrête le saut de page lors du défilement vers le hachage cible.

1
vibrationbaby

Ceci est un extrait jQuery que j'utilise et que je trouve très ingénieux et flexible. Vous pouvez supprimer le DOM Ready si vous l'exécutez dans le pied de page qui est suggéré. Il vous suffit de charger n'importe quelle bibliothèque post 1.4v avant celle-ci. Il écoute tous les clics sur les ancres, puis il exécute un booléen et un OR pour les vérifications de classe. S'il trouve une classe, il exécute le script et l'animation. Vous pouvez ajuster votre décalage à partir de son position finale, je préfère 60px sur la plupart des applications, mais n'hésitez pas à régler au besoin.

<!--jQuerySmoothScroll-->
<script>
jQuery(document).ready(function(){
        // Add smooth scrolling to all links
        jQuery("a").on('click', function(event) {
      //check that we have the smooth-scroll class add as many as need be
            if (jQuery(this).hasClass("whatever-class-you-want") || jQuery(this).hasClass("smooth-scroll")) {
                        // Make sure this.hash has a value before overriding default behavior
                                        if (this.hash !== "") {
                                        // Prevent default anchor click behavior
                                event.preventDefault();
                        // Store hash
                        var hash = this.hash;
                // Using jQuery's animate() method to add smooth page scroll
                // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
        jQuery('html, body').animate({
        scrollTop: jQuery(hash).offset().top-60// Set offset from top position
       }, 800, function(){
   
        // Add hash (#) to URL when done scrolling (default click behavior)
        window.location.hash = hash;
      });
     } // End if
    } // End if (class)
  });
});
</script>
1
Garrick Crouch

Voici ce que j'utilise. Réglez le décalage selon vos besoins.

$('a[href^="#"]').click(function(e) {
  e.preventDefault();
  $(window).stop(true).scrollTo(this.hash {duration:1000,interrupt:true,offset: -50});
});
0
cdrck

Il s'agit d'une implémentation jQuery que j'utilise qui était basée sur la solution de Никита Андрейчук. La variable d'ajustement des pixels peut être définie dynamiquement de cette façon, bien qu'elle soit codée en dur dans cet exemple.

$( 'a' ).each(function() {
    var pixels = 145;
    var name = $( this ).attr( 'name' );
    if ( typeof name != 'undefined' ) {
        $( this ).css({
          'display'    : 'block',
          'height'     : pixels + 'px',
          'margin-top' : '-' + pixels + 'px',
          'visibility' : 'hidden'
        });
    }
});
0
Jeremy Morgan