AngularJS - $ anchorScroll mulus / durasi


115

Membaca dokumen AngularJS Saya belum tahu apakah $anchorScrolldapat memiliki opsi durasi / pelonggaran untuk menggulir mulus ke elemen.

Itu hanya mengatakan:

$location.hash('bottom');

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

Saya tidak menggunakan jquery dan tidak mau; apakah masih ada cara yang cerdas namun sederhana untuk membuat atau memperluas $anchorScrollagar pengguliran lebih lancar?

Jawaban:


155

Sayangnya ini tidak mungkin digunakan $anchorScroll. Seperti yang Anda temukan $anchorScrolltidak memiliki opsi apa pun dan tidak berfungsi $ngAnimate. Untuk menganimasikan gulungan, Anda perlu menggunakan layanan / pabrik Anda sendiri atau hanya javascript langsung.

Demi belajar mandiri, saya mengumpulkan contoh dengan layanan scrolling yang lancar. Mungkin ada cara yang lebih baik untuk melakukan ini sehingga setiap umpan balik dianjurkan.

Untuk menggulir ke elemen, Anda melampirkan ng-click="gotoElement(ID)"ke elemen apa pun. Saya pikir rute yang lebih baik adalah menjadikan ini arahan.

Berikut contoh kerja di jsFiddle .

Memperbarui

Sekarang ada sejumlah arahan pihak ketiga untuk mencapai ini.


11
Sangat bagus. Ini dia sebagai petunjuknya: gist.github.com/justinmc/d72f38339e0c654437a2
Justin McCandless

@JustinMcCandless bagaimana Anda menyebut direktif Anda? Saya sudah mencoba: <a ng-click="anchor-smooth-school('about');"> About 1 </a> <a ng-click="anchorSmoothScroll('about');"> About 2 < / a>
Dan

1
@Dan lakukan saja<a anchor-smooth-scroll>About 1</a> <a anchor-smooth-scroll>About 2</a>
Justin McCandless

1
Bagus, saya suka jawaban ini. Tapi ini masih menambah alasan lain untuk membenci AngularJS, maksud saya, lihat ukurannya dibandingkan dengan JQuery scrollTo
Felype

1
Untuk menggunakan direktif, membuat elemen dengan ID (misalnya <div id="my-div">my div</div>) dan kemudian membuat link seperti ini: <a anchor-smooth-scroll="my-div">visit my div</a>.
Jason Swett

20

Anda juga dapat menggunakan angular-scroll, link " https://github.com/durated/angular-scroll/ ". Ini adalah pengguliran halus juga beberapa fungsi easing untuk mendapatkan tampilan profesional.


1
Apakah plugin ini berfungsi pada elemen lain selain dari $ documents? Saya mencoba menerapkan scrollToElement ke div sehingga saya dapat menggulir baris di dalamnya ke tampilan, dan tidak berhasil ..
Shaunak

10

Jawaban dari Brett sangat bermanfaat bagi saya. Saya melakukan beberapa perubahan kecil pada solusinya dalam hal modularisasi dan testability.

Berikut adalah contoh kerja lain di JsFiddle yang menyertakan versi lain dengan pengujian yang disertakan.

Untuk pengujian, saya menggunakan Karma dan Jasmine. Tanda tangan telah sedikit dimodifikasi sebagai berikut:

 anchorSmoothScroll.scrollTo(elementId, speed);

Di mana elemen adalah atribut wajib untuk menggulir dan kecepatan adalah opsional di mana defaultnya adalah 20 (seperti sebelumnya).



2

Tidak ada solusi di sini yang benar-benar melakukan apa yang diminta OP, yaitu, membuat $anchorScrollpengguliran lancar. Perbedaan antara perintah scroll halus dan perintah $anchroScrollmenggunakan / memodifikasi $location.hash(), yang mungkin diinginkan dalam beberapa kasus.

Berikut adalah inti dari modul sederhana yang menggantikan scrolling $ anchorScroll dengan scrolling mulus. Ini menggunakan perpustakaan https://github.com/oblador/angular-scroll untuk pengguliran itu sendiri (ganti dengan yang lain jika Anda mau, itu harus mudah).

https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
Catatan: Sebenarnya $ anchorScroll tidak dapat menggulir dengan lancar, tetapi menggantikan penangannya untuk menggulir.

Aktifkan hanya dengan mereferensikan mdvorakSmoothScrollmodul di aplikasi Anda.


0

Alan, terima kasih. Jika ada yang berminat, saya memformatnya berdasarkan standar 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

Saya tidak tahu bagaimana cara menghidupkan $anchorScroll. Inilah cara saya melakukannya dalam proyek saya:

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

Dan fungsi 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;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.