115

Reading the AngularJS docs I haven't figured out if $anchorScroll can have a duration/easing option to smooth scroll to elements.

It only says:

$location.hash('bottom');

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

I do not use jquery and don't want to; is there still a clever yet simple way to make or extend $anchorScroll in order to make scrolling more smooth?

4

8 回答 8

156

不幸的是,这是不可能的$anchorScroll。正如您发现$anchorScroll的那样,它没有任何选项并且不适用于$ngAnimate. 为了使滚动动画化,您需要使用自己的服务/工厂或直接使用 javascript。

为了自学,我整理了一个带有平滑滚动服务的示例。可能有更好的方法可以做到这一点,因此鼓励任何反馈。

要滚动到一个元素,您将 a 附加ng-click="gotoElement(ID)"到任何元素。我认为更好的方法是将此作为指令。

这是jsFiddle 上的工作示例

更新

现在有许多第三方指令可以实现这一点。

于 2014-02-20T20:12:52.543 回答
20

您还可以使用 angular-scroll,链接“ https://github.com/durated/angular-scroll/ ”。它是平滑的滚动,也很少有缓动功能来获得专业的外观。

于 2014-06-03T12:14:19.397 回答
10

布雷特的回答对我很有用。我在模块化和可测试性方面对他的解决方案做了一些小的改动。

这是 JsFiddle 上的另一个工作示例,其中包括包含测试的其他版本。

对于测试,我使用的是 Karma 和 Jasmine。签名稍作修改如下:

 anchorSmoothScroll.scrollTo(elementId, speed);

其中 element 是必须滚动到的属性,而 speed 是可选的,默认值为 20(和以前一样)。

于 2014-05-15T19:37:59.840 回答
2

你也可以使用 ngSmoothScroll,链接:https ://github.com/d-oliveros/ngSmoothScroll 。

只需将smoothScroll模块包含为依赖项并像这样使用它:

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

于 2015-03-10T00:47:01.237 回答
2

这里的解决方案都没有真正做到 OP 最初要求的,即$anchorScroll平滑滚动。平滑滚动指令之间的区别在于$anchroScroll它使用/修改$location.hash(),这在某些情况下可能是可取的。

这是用平滑滚动替换 $anchorScroll 滚动的简单模块的要点。它使用https://github.com/oblador/angular-scroll库进行滚动本身(如果需要,可以用其他东西替换它,应该很容易)。

https://gist.github.com/mdvorak/fc8b531d3e082f3fdaa9
注意:它实际上并没有让 $anchorScroll 平滑滚动,而是替换了它的滚动处理程序。

mdvorakSmoothScroll只需在应用程序中引用模块即可启用它。

于 2015-03-10T09:10:07.420 回答
0

我们可以将 JQuery 和 Javascript 与 Directive 一起使用,以在单击锚标记时滚动到特定的 div。

请检查以下链接上的工作示例 -

https://stackoverflow.com/a/67513880/6656918

于 2021-05-13T04:28:16.300 回答
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);
                }
            }

        }

    };

};

})();
于 2016-05-06T15:51:36.803 回答
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;
}
于 2017-10-24T11:33:22.317 回答