web-dev-qa-db-fra.com

Événement de défilement agité / décalé sur Chrome et IE

J'essaie de toujours montrer un bloc de contenu à l'utilisateur, même s'il fait défiler vers le bas de la page. Il devrait également pouvoir faire défiler le bloc de contenu de haut en bas. Voici un violon avec une version allégée pour vous montrer ce que je veux dire:

http://jsfiddle.net/9ehfV/2/

Il faut remarquer lors du défilement vers le bas, jusqu'à ce qu'il atteigne le bas du bloc rouge, il fixera le bloc sur la fenêtre, et lors du défilement vers le haut, il le replacera.

Dans Firefox, on peut faire défiler vers le haut et vers le bas et la fixation/déblocage décrite ci-dessus est imperceptible - lisse comme de la soie.

Une fois que l'on essaie de faire défiler Chrome ou IE, cependant, il semble que l'événement de défilement soit en retard et que l'on puisse voir le bloc "glitching" pendant une seconde. Ce n'est pas du retard de code - il semble être quelque chose avec les navigateurs.

Est-ce qu'il y a un moyen de réparer ceci? Je suis à bout de souffle.

J'apprécierais des suggestions sur la façon dont je peux obtenir le même effet d'une manière différente ... merci

27
Marcelo Mason

Étant donné que JavaScript s'exécute dans le même thread que l'interface utilisateur, un rappel d'événement de défilement peut bloquer le thread d'interface utilisateur et ainsi provoquer un décalage. Vous devez limiter l'écouteur d'événements de défilement, car certains navigateurs en déclenchent beaucoup. Surtout si vous êtes sous OS X avec un périphérique de défilement analogique. Puisque vous faites beaucoup de calculs de hauteur dans votre écouteur, cela déclenchera une redistribution (très cher) pour chaque événement de défilement qui est déclenché.

Pour limiter l'auditeur, vous devez l'empêcher de se déclencher à chaque fois. Habituellement, vous attendez que le navigateur ne déclenche pas d'événement pendant x millisecondes, ou disposez d'un délai minimum entre l'appel de votre rappel. Essayez d'ajuster la valeur pour voir l'effet. Même 0 millisecondes peut aider, car cela retardera l'exécution du rappel jusqu'à ce que le navigateur ait le temps (généralement 5-40 ms).

Il est également recommandé de basculer une classe pour basculer entre les états (position statique et position fixe) au lieu de la coder en dur en JavaScript. Ensuite, vous avez une séparation plus nette des préoccupations et évitez les redessins supplémentaires potentiels par erreur (voir la section "Les navigateurs sont intelligents"). ( exemple sur jsfiddle )

Attendez une pause de x ms

// return a throttled function
function waitForPause(ms, callback) {
    var timer;

    return function() {
        var self = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            callback.apply(self, args);
        }, ms);
    };
}

this.start = function() {
    // wrap around your callback
    $window.scroll( waitForPause( 30, self.worker ) );
};

Attendez au moins x ms ( jsfiddle )

function throttle(ms, callback) {
    var timer, lastCall=0;

    return function() {
        var now = new Date().getTime(),
            diff = now - lastCall;
        console.log(diff, now, lastCall);
        if (diff >= ms) {
            console.log("Call callback!");
            lastCall = now;
            callback.apply(this, arguments);
        }
    };
}

this.start = function() {
    // wrap around your callback
    $window.scroll(throttle(30, self.worker));
};

jQuery Waypoints Puisque vous utilisez déjà jQuery, j'aimerais jeter un œil au plug-in jQuery Waypoints qui a un simple et solution élégante à votre problème. Définissez simplement un rappel lorsque l'utilisateur fait défiler jusqu'à un certain point de cheminement.

Exemple: ( jsfiddle )

$(document).ready(function() {
    // throttling is built in, just define ms
    $.waypoints.settings.scrollThrottle = 30;

    $('#content').waypoint(function(event, direction) {
        $(this).toggleClass('sticky', direction === "down");
        event.stopPropagation();
    }, {
        offset: 'bottom-in-view' // checkpoint at bottom of #content
    });
});
44
gregers

Avez-vous essayé un plugin jquery pour la barre de défilement ou utilisez l'animation pour faire défiler vers le haut et vers le bas? Cela forcera tous les navigateurs à fonctionner de la même manière (ou se fermera suffisamment).

Ce qui se passe, c'est que Firefox (au moins v12) a une animation de défilement "native". Lorsque vous naviguez pour une URL, vous pouvez remarquer la fluidité des actions de défilement et cela n'est pas implémenté dans d'autres navigateurs, comme Chrome ou IE.

Exemples de plugins jquery scroller:

1
Rafael Verger