【问题标题】:AngularJS - $anchorScroll smooth/durationAngularJS - $anchorScroll 平滑/持续时间
【发布时间】:2014-03-12 01:46:26
【问题描述】:

阅读AngularJS docs 我还没有弄清楚$anchorScroll 是否可以有一个持续时间/缓动选项来平滑滚动到元素。

它只是说:

$location.hash('bottom');

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

我不使用 jquery,也不想;是否还有一种巧妙而简单的方法来制作或扩展$anchorScroll 以使滚动更流畅?

【问题讨论】:

    标签: javascript angularjs scroll anchor-scroll


    【解决方案1】:

    我们可以使用 JQuery 和 Javascript 和 Directive 来在锚点标签点击时滚动到特定的 div。

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

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

    【讨论】:

      【解决方案2】:

      我不知道如何为 $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;
      }
      

      【讨论】:

        【解决方案3】:

        艾伦,谢谢。如果有人感兴趣,我会根据 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);
                        }
                    }
        
                }
        
            };
        
        };
        
        })();
        

        【讨论】:

          【解决方案4】:

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

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

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

          这是working example on jsFiddle

          更新

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

          【讨论】:

          • 非常好。这是一个指令:gist.github.com/justinmc/d72f38339e0c654437a2
          • @JustinMcCandless 你怎么称呼你的指令?我试过:大约 1 大约 2
          • @Dan 做&lt;a anchor-smooth-scroll&gt;About 1&lt;/a&gt; &lt;a anchor-smooth-scroll&gt;About 2&lt;/a&gt;
          • 很好,我喜欢这个答案。但这仍然增加了讨厌AngularJS的另一个原因,我的意思是,看看这个与JQuery scrollTo相比的大小
          • 要使用该指令,请创建一个带有 ID 的元素(例如 &lt;div id="my-div"&gt;my div&lt;/div&gt;),然后创建如下链接:&lt;a anchor-smooth-scroll="my-div"&gt;visit my div&lt;/a&gt;
          【解决方案5】:

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

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

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

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

          【讨论】:

            【解决方案6】:

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

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

            &lt;a href="#" scroll-to="my-element-3"&gt;Click me!&lt;/a&gt;

            【讨论】:

              【解决方案7】:

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

              【讨论】:

              • 除了 $documents 之外,这个插件是否适用于其他元素?我尝试将 scrollToElement 应用于 div,以便可以将其中的一行滚动到视图中,但它不起作用..
              【解决方案8】:

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

              这是另一个 working example on JsFiddle,其中包含另一个版本,其中包含测试。

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

               anchorSmoothScroll.scrollTo(elementId, speed);
              

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

              【讨论】:

                猜你喜欢
                • 2021-10-19
                • 2021-03-31
                • 2012-12-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-08-09
                • 1970-01-01
                • 2018-08-30
                相关资源
                最近更新 更多