AngularJS-$ anchorScrollスムーズ/期間


115

AngularJSのドキュメントを読んで、$anchorScroll要素までスムーズにスクロールするための期間/イージングオプションがあるかどうかはわかりません。

それは言うだけです:

$location.hash('bottom');

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

私はjqueryを使用せず、使用したくありません。$anchorScrollスクロールをよりスムーズにするために、作成または拡張するための賢いまだ簡単な方法はまだありますか?

回答:


155

残念ながら、これを使用してこれを行うことはできません$anchorScroll。あなたが発見$anchorScrollしたように、オプションはなく、で動作しません$ngAnimate。スクロールをアニメーション化するには、独自のサービス/工場または単なるjavascriptを使用する必要があります。

自己学習のために、スムーズなスクロールサービスを使用した例を作成しました。これを行うにはもっと良い方法があると思われるので、フィードバックをお勧めします。

要素にスクロールするには、ng-click="gotoElement(ID)"任意の要素にをアタッチします。私はこれを指令にする方がより良いルートだと思います。

これがjsFiddle実際の例です

更新

これを達成するためのサードパーティのディレクティブがいくつかあります。


11
非常に素晴らしい。これはディレクティブです:gist.github.com/justinmc/d72f38339e0c654437a2
Justin McCandless

@JustinMcCandlessディレクティブをどのように呼び出すのですか?試しました:<a ng-click="anchor-smooth-school('about');"> 1について</a> <a ng-click="anchorSmoothScroll('about');"> 2について< />
ダン

1
@Danはただやる<a anchor-smooth-scroll>About 1</a> <a anchor-smooth-scroll>About 2</a>
Justin McCandless 14

1
いいですね、この答えが好きです。しかし、これは、AngularJSを嫌う別の理由を追加します。
つまり

1
ディレクティブを使用するには、IDを使用して要素を作成し(例:)<div id="my-div">my div</div>、次のようなリンクを作成します<a anchor-smooth-scroll="my-div">visit my div</a>
Jason Swett

20

angular-scrollを使用して、「https://github.com/durated/angular-scroll/」にリンクすることもできます。それはスムーズなスクロールであり、プロの外観を得るいくつかのイージング関数です。


1
このプラグインは$ documents以外の要素でも機能しますか?..私は、私はビューにその中の行をスクロールすることができるようにdiv要素にscrollToElementを適用しようとしました、そしてそれはうまくいきませんでした
Shaunak

10

ブレットからの答えは私にとってはうまくいきました。モジュール化とテスト容易性の点で彼のソリューションにいくつかの小さな変更を加えました。

以下は、テストが含まれた他のバージョンを含むJsFiddleのもう 1つの実用的な例です。

テストには、カルマとジャスミンを使用しています。署名は次のように少し変更されています。

 anchorSmoothScroll.scrollTo(elementId, speed);

要素はスクロール先の必須属性であり、速度はオプションです。デフォルトは20です(以前と同様)。



2

ここでの解決策はいずれも、OPが最初に要求したことを実際に実行するものではありません$anchorScroll。つまり、スクロールをスムーズにします。スムーズスクロールディレクティブとの違い$anchroScrollは、を使用/変更すること$location.hash()であり、場合によっては望ましい場合があります。

$ anchorScrollスクロールをスムーズスクロールに置き換える単純なモジュールの要点を次に示します。スクロール自体にはhttps://github.com/oblador/angular-scrollライブラリを使用します(必要に応じて他のものと置き換えてください。簡単にできます)。

https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
注:実際には、$ anchorScrollでスムーズにスクロールすることはできませんが、スクロール用のハンドラーを置き換えます。

mdvorakSmoothScrollアプリケーションでモジュールを参照するだけで有効にできます。


0

アラン、ありがとう。興味があれば、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

アニメーションの仕方がわかりません$anchorScroll。これが私のプロジェクトでのやり方です:

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

そして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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.