AngularJS - $ anchorScroll glatt / Dauer


115

Lesen der AngularJS-Dokumente Ich habe nicht herausgefunden, ob $anchorScrolles eine Dauer- / Beschleunigungsoption zum reibungslosen Scrollen zu Elementen geben kann.

Es heißt nur:

$location.hash('bottom');

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

Ich benutze keine Abfrage und möchte nicht; Gibt es noch eine clevere und dennoch einfache Möglichkeit zum Erstellen oder Erweitern $anchorScroll, um das Scrollen reibungsloser zu gestalten?

Antworten:


155

Dies ist leider nicht möglich $anchorScroll. Wie Sie festgestellt $anchorScrollhaben, hat keine Optionen und funktioniert nicht mit $ngAnimate. Um die Schriftrolle zu animieren, müssten Sie Ihren eigenen Service / Ihre eigene Fabrik oder nur Javascript verwenden.

Um selbst zu lernen, habe ich ein Beispiel mit einem reibungslosen Bildlauf zusammengestellt. Es gibt wahrscheinlich bessere Möglichkeiten, dies zu tun, sodass jedes Feedback ermutigt wird.

Um zu einem Element zu scrollen, hängen Sie ein an ein ng-click="gotoElement(ID)"beliebiges Element an. Ich denke, ein noch besserer Weg wäre, dies zu einer Richtlinie zu machen.

Hier ist das Arbeitsbeispiel für jsFiddle .

Aktualisieren

Es gibt jetzt eine Reihe von Richtlinien von Drittanbietern, um dies zu erreichen.


11
Sehr schön. Hier ist es als Richtlinie: gist.github.com/justinmc/d72f38339e0c654437a2
Justin McCandless

@JustinMcCandless Wie nennt man deine Direktive? Ich habe versucht: <a ng-click="anchor-smooth-school('about');"> Ungefähr 1 </a> <a ng-click="anchorSmoothScroll('about');"> Ungefähr 2 < / a>
Dan

1
@ Dan einfach tun<a anchor-smooth-scroll>About 1</a> <a anchor-smooth-scroll>About 2</a>
Justin McCandless

1
Schön, ich mag diese Antwort. Aber dies fügt noch einen weiteren Grund hinzu, AngularJS zu hassen. Ich meine, sehen Sie sich die Größe im Vergleich zu JQuery scrollTo
Felype

1
Um die Direktive zu verwenden, erstellen Sie ein Element mit einer ID (z. B. <div id="my-div">my div</div>) und erstellen Sie dann einen Link wie folgt : <a anchor-smooth-scroll="my-div">visit my div</a>.
Jason Swett

20

Sie können auch die Winkelrolle verwenden, Link " https://github.com/durated/angular-scroll/ ". Es ist sanftes Scrollen sowie einige Beschleunigungsfunktionen, um ein professionelles Aussehen zu erhalten.


1
Funktioniert dieses Plugin auch für andere Elemente als $ Dokumente? Ich habe versucht, scrollToElement auf ein div anzuwenden, damit ich eine Zeile darin in die Ansicht scrollen kann, und es hat nicht funktioniert.
Shaunak

10

Die Antwort von Brett hat für mich großartig funktioniert. Ich habe einige kleine Änderungen an seiner Lösung in Bezug auf Modularisierung und Testbarkeit vorgenommen.

Hier ist ein weiteres Arbeitsbeispiel für JsFiddle , das die andere Version mit Tests enthält.

Zum Testen benutze ich Karma und Jasmine. Die Signatur wurde wie folgt leicht geändert:

 anchorSmoothScroll.scrollTo(elementId, speed);

Wobei Element ein obligatorisches Attribut ist, zu dem gescrollt werden soll, und Geschwindigkeit optional ist, wobei der Standardwert 20 ist (wie zuvor).



2

Keine der Lösungen hier macht tatsächlich das, was OP ursprünglich verlangt hatte, $anchorScrolldh macht das Scrollen reibungslos. Der Unterschied zwischen Anweisungen zum reibungslosen Scrollen $anchroScrollbesteht darin, dass sie verwendet / geändert werden $location.hash(), was in einigen Fällen wünschenswert sein kann.

Hier ist das Wesentliche für ein einfaches Modul, das das Scrollen von $ anchorScroll durch ein reibungsloses Scrollen ersetzt. Es verwendet die Bibliothek https://github.com/oblador/angular-scroll für das Scrollen selbst (ersetzen Sie es durch etwas anderes, wenn Sie möchten, es sollte einfach sein).

https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Hinweis: $ anchorScroll kann nicht reibungslos gescrollt werden, ersetzt jedoch den Handler zum Scrollen.

Aktivieren Sie es einfach, indem Sie auf das mdvorakSmoothScrollModul in Ihrer Anwendung verweisen .


0

Alan, danke. Wenn jemand interessiert ist, habe ich es basierend auf John Pappa Standards formatiert.

(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

Ich weiß nicht, wie ich animieren soll $anchorScroll. So mache ich das in meinen Projekten:

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

Und die JS-Funktion:

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.