web-dev-qa-db-fra.com

Prise en compte d'un en-tête fixe avec animate.scrolltop et (target) .offset (). Top;

Cela devrait être une question assez basique, mais j'y ai jeté la majeure partie de ma matinée, et à ce stade, je suis sur le point de jeter l'éponge. Je n'ai même pas un peu de js foo - mais j'ai trouvé un morceau de code bien commenté que j'espère utiliser pour animer des liens d'ancrage, c'est:

$(document).ready(function() {
$('a[href*=#]').bind('click', function(e) {
e.preventDefault(); //prevent the "normal" behaviour which would be a "hard" jump

var target = $(this).attr("href"); //Get the target

var scrollToPosition = $(target).offset().top;

// perform animated scrolling by getting top-position of target-element and set it     as scroll target
$('html, body').stop().animate({ scrollTop: scrollToPosition}, 600, function() {
     location.hash = target;  //attach the hash (#jumptarget) to the pageurl
});

return false;

 });
});

J'essaie de le faire atterrir à 30 pixels au-dessus du décalage (). Top - J'ai essayé

$('html, body').stop().animate({ scrollTop: scrollToPosition -30}, 600,

Ce qui fonctionne presque - il va au bon endroit mais rebondit ensuite.

J'ai aussi essayé

scrollTop: $(target).offset().top - 20 },

J'ai aussi essayé

scrollTop: $(hash).offset().top + $('#access').outerHeight()

Ce qui ne semble rien changer.

Il semble que la réponse soit ici: problème de défilement de la page JQuery avec un en-tête fixe mais je n'arrive tout simplement pas à l'obtenir.

Je sais que cela est similaire à d'autres questions - mais j'ai parcouru ce que j'ai pu trouver et je suis assez analphabète pour ne pas avoir été en mesure de copier/coller quoi que ce soit qui résout le problème.

Je serais incroyablement reconnaissant pour une solution.

Merci beaucoup,

Martin

PS

Cet autre morceau de code que j'ai trouvé fonctionne, mais il supprime le hashtag, ce qui le rend presque inutile.

$(function(){
$('a[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) {
            var targetOffset = $target.offset().top;
            $('html,body').animate({scrollTop: targetOffset - 30}, 1000);
            return false;
        }
    }
  });
});
14
Martin

EDITED: Il vous suffit de détecter la hauteur de l'en-tête fixe et de la soustraire de scrollToPosition que vous faisiez correctement. Le problème est le window.location.hash = "" + target; saute la page en haut de l'élément avec cet identifiant. Donc, si vous y animez comme vous le faisiez et que vous passez ensuite à ce hachage, il "rebondira" comme vous l'avez décrit. Voici la première façon de lutter contre cela:

// Get the height of the header
var headerHeight = $("div#header").height();

// Attach the click event
$('a[href*=#]').bind("click", function(e) {
    e.preventDefault();

    var target = $(this).attr("href"); //Get the target
    var scrollToPosition = $(target).offset().top - headerHeight;

    $('html').animate({ 'scrollTop': scrollToPosition }, 600, function(){
        window.location.hash = "" + target;
        // This hash change will jump the page to the top of the div with the same id
        // so we need to force the page to back to the end of the animation
        $('html').animate({ 'scrollTop': scrollToPosition }, 0);
    });

    $('body').append("called");
});

Voici un nouveau jsfiddle pour cette première méthode: http://jsfiddle.net/yjcRv/1/

MODIFICATION SUPPLÉMENTAIRE: Une façon encore meilleure de contrôler les événements de changement de hachage consiste à utiliser un plugin comme jQuery Address . Avec cela, vous pouvez utiliser vos événements de changement de hachage beaucoup plus. Voici un exemple d'utilisation:

// Get the height of the header
var headerHeight = $("div#header").height();

$.address.change(function(evt){
    var target = "#" + evt["pathNames"][0]; //Get the target from the event data

    // If there's been some content requested go to it…else go to the top
    if(evt["pathNames"][0]){
        var scrollToPosition = $(target).offset().top - headerHeight;
        $('html').animate({ 'scrollTop': scrollToPosition }, 600);
    }else{
        $('html').animate({ 'scrollTop': '0' }, 600);
    }

    return false;
});

// Attach the click event
$('a').bind("click", function(e) {
    // Change the location
    $.address.value($(this).attr("href"));

    return false;
});

Exemple en direct ici: http://www.vdotgood.com/stack/user3444.html

REMARQUE: vous n'avez pas besoin d'ajouter le hachage à votre attribut href de liens maintenant. Voici un lien que vous pouvez cibler avec un sélecteur jQuery:

<!-- This is correct -->
<a href="/target" class="myclass">Target</a>

<!-- These are incorrect -->
<a href="/#/target" class="myclass">Target</a>

<a href="#/target" class="myclass">Target</a>

Pour cibler ce lien, vous utiliseriez un sélecteur comme:

$("a.myclass").click(function(){
    $.address.value($(this).attr("href"));
    return false;
});

jQuery Address recherche en fait des liens qui ont l'attribut suivant:

<a href="/target" rel="address:/target">Target</a>

L'attribut rel contient ici address: suivi d'une URL relative définie par vous dans ce cas /target. Si vous l'utilisez, jQuery Address détectera le lien et déclenchera automatiquement l'événement de changement de hachage.

16
Steve O

Je sais que c'est une vieille question (en quelque sorte), mais j'ai rencontré un problème similaire avec une navigation déroulante fixe sur un site Web. Notez qu'il s'agit d'un extrait de code de défilement fluide, bien que vous puissiez facilement le rendre automatique en modifiant la vitesse d'animation.

jQuery:

$('body').on('click','a[href^="#"]',function(event){
    event.preventDefault();
    var target_offset = $(this.hash).offset() ? $(this.hash).offset().top : 0;
    //change this number to create the additional off set        
    var customoffset = 75
    $('html, body').animate({scrollTop:target_offset - customoffset}, 500);
});

J'ai utilisé ce morceau de code pendant longtemps sans aucun problème. La seule chose que je n'aime pas à ce sujet, c'est qu'il saisira n'importe quelle balise #. Donc, dans un plugin comme le plugin Flexslider où la navigation utilise #, je les supprime manuellement du plugin.

7
GregT

J'ai modifié le script original de http://www.paulund.co.uk/smooth-scroll-to-internal-links-with-jquery . Cela fonctionne à merveille mais vous ne pouvez pas définir un délai tel quel.

var headerHeight = $("header").height();


        $(document).ready(function(){
    $('a[href^="#"]').on('click',function (e) {
        e.preventDefault();

        var target = this.hash,
        $target = $(target);

        $('html, body').stop().animate({
            'scrollTop': $target.offset().top - headerHeight
        }, 1200, 'swing', function () {
            window.location.hash = target ;
        });
    });
});

Oui, je suis un peu en retard mais ce problème m'est venu à l'esprit ... A bientôt!

3
Neurone00