web-dev-qa-db-fra.com

AngularJS - $ anchorScroll lisse / durée

Lecture de la documentation AngularJS Je ne sais pas si $anchorScroll peut avoir une option de durée/accélération pour un défilement régulier des éléments.

Il dit seulement:

$location.hash('bottom');

// call $anchorScroll()
$anchorScroll();

Je n'utilise pas jquery et je ne veux pas; existe-t-il encore un moyen simple mais intelligent de créer ou d'étendre $anchorScroll afin de rendre le défilement plus fluide?

112
itsme

Malheureusement, ceci n'est pas possible avec $anchorScroll. Comme vous l'avez découvert, $anchorScroll n'a pas d'options et ne fonctionne pas avec $ngAnimate. Pour animer le parchemin, vous devez utiliser votre propre service/usine ou simplement du javascript.

Par souci d’auto-apprentissage, j’ai rassemblé un exemple avec un service de défilement régulier. Il y a probablement de meilleures façons de le faire, donc tout retour d'information est encouragé.

Pour faire défiler un élément, vous associez un ng-click="gotoElement(ID)" à un élément. Je pense qu'une solution encore meilleure serait d'en faire une directive.

Voici le exemple de travail sur jsFiddle .

Mettre à jour

Il existe maintenant un certain nombre de directives de tiers pour accomplir cela.

152
Brett DeWoody

Vous pouvez également utiliser le lien angular-scroll, " https://github.com/dured/angular-scroll/ ". Il s'agit d'un défilement régulier et de quelques fonctions d'assouplissement permettant d'obtenir un aspect professionnel.

20
Sagar Parikh

La réponse de Brett a très bien fonctionné pour moi. J'ai apporté quelques modifications mineures à sa solution en termes de modularisation et de testabilité.

Voici encore un autre exemple de travail sur JsFiddle qui inclut l’autre version avec les tests inclus.

Pour tester, j'utilise Karma et Jasmine. La signature a été légèrement modifiée comme suit:

 anchorSmoothScroll.scrollTo(elementId, speed);

Où element est un attribut obligatoire auquel faire défiler et où speed est facultatif, la valeur par défaut étant 20 (comme auparavant).

10
Alan Souza

Vous pouvez également utiliser ngSmoothScroll, link: https://github.com/d-oliveros/ngSmoothScroll .

Incluez simplement le module smoothScroll comme dépendance et utilisez-le comme ceci:

<a href="#" scroll-to="my-element-3">Click me!</a>

2
santiaago

Aucune des solutions ici ne fait réellement ce que l'OP a demandé à l'origine, à savoir, faire défiler $anchorScroll en douceur. La différence entre les directives de défilement régulier et $anchroScroll réside dans le fait qu’il utilise/modifie $location.hash(), ce qui peut être souhaitable dans certains cas.

Voici Gist pour le module simple qui remplace le défilement $ anchorScroll par le défilement régulier. Il utilise https://github.com/oblador/angular-scroll bibliothèque pour le défilement lui-même (remplacez-le par autre chose si vous voulez, cela devrait être facile).

https://Gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Note: En réalité, $ anchorScroll ne défile pas en douceur, mais il remplace son gestionnaire pour le défilement.

Activez-le simplement en référençant le module mdvorakSmoothScroll de votre application.

2
Mikee

Je ne sais pas comment animer $anchorScroll. Voici comment je le fais dans mes projets:

/* Scroll to top on each ui-router state change */
$rootScope.$on('$stateChangeStart', function() {
 scrollToTop();
});

Et la fonction JS:

function scrollToTop() {
    if (typeof jQuery == 'undefined') {
        return window.scrollTo(0,0);
    } else {
        var body = $('html, body');
        body.animate({scrollTop:0}, '600', 'swing');
    }
    log("scrollToTop");
    return true;
}
0
Deepak Thomas

Alan, merci. Si cela intéresse quelqu'un, je l'ai formaté en fonction des normes John Pappa.

(function() {

'use strict';
var moduleId = 'common';
var serviceId = 'anchorSmoothScroll';

angular
    .module(moduleId)
    .service(serviceId, anchorSmoothScroll);

anchorSmoothScroll.$inject = ['$document', '$window'];

function anchorSmoothScroll($document, $window) {

    var document = $document[0];
    var window = $window;

    var service = {
        scrollDown: scrollDown,
        scrollUp: scrollUp,
        scrollTo: scrollTo,
        scrollToTop: scrollToTop
    };
    return service;

    function getCurrentPagePosition(currentWindow, doc) {
        // Firefox, Chrome, Opera, Safari
        if (currentWindow.pageYOffset) return currentWindow.pageYOffset;
        // Internet Explorer 6 - standards mode
        if (doc.documentElement && doc.documentElement.scrollTop)
            return doc.documentElement.scrollTop;
        // Internet Explorer 6, 7 and 8
        if (doc.body.scrollTop) return doc.body.scrollTop;
        return 0;
    }

    function getElementY(doc, element) {
        var y = element.offsetTop;
        var node = element;
        while (node.offsetParent && node.offsetParent !== doc.body) {
            node = node.offsetParent;
            y += node.offsetTop;
        }
        return y;
    }

    function scrollDown(startY, stopY, speed, distance) {

        var timer = 0;

        var step = Math.round(distance / 25);
        var leapY = startY + step;

        for (var i = startY; i < stopY; i += step) {
            setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
            leapY += step;
            if (leapY > stopY) leapY = stopY;
            timer++;
        }
    };

    function scrollUp(startY, stopY, speed, distance) {

        var timer = 0;

        var step = Math.round(distance / 25);
        var leapY = startY - step;

        for (var i = startY; i > stopY; i -= step) {
            setTimeout('window.scrollTo(0, ' + leapY + ')', timer * speed);
            leapY -= step;
            if (leapY < stopY) leapY = stopY;
            timer++;
        }
    };

    function scrollToTop(stopY) {
        scrollTo(0, stopY);
    };

    function scrollTo(elementId, speed) {

        var element = document.getElementById(elementId);

        if (element) {
            var startY = getCurrentPagePosition(window, document);
            var stopY = getElementY(document, element);

            var distance = stopY > startY ? stopY - startY : startY - stopY;

            if (distance < 100) {
                this.scrollToTop(stopY);

            } else {

                var defaultSpeed = Math.round(distance / 100);
                speed = speed || (defaultSpeed > 20 ? 20 : defaultSpeed);

                if (stopY > startY) {
                    this.scrollDown(startY, stopY, speed, distance);
                } else {
                    this.scrollUp(startY, stopY, speed, distance);
                }
            }

        }

    };

};

})();
0
Rentering.com