AngularJS-$anchor 滚动平滑/持续时间

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

它只是说:

$location.hash('bottom');


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

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

98900 次浏览

不幸的是,使用 $anchorScroll不可能做到这一点。正如您所发现的,$anchorScroll没有任何选项,也不能与 $ngAnimate一起工作。为了使滚动动画化,你需要使用你自己的服务/工厂或者直接使用 javascript。

为了自学,我用一个平滑的滚动服务组合了一个例子。可能有更好的方法来做到这一点,所以任何反馈都是鼓励的。

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

这是 JsFiddle 上的工作示例

更新

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

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

下面是另一个包含测试的 JsFiddle 的工作示例版本。

为了测试,我使用了 Karma 和 Jasmine。签名稍微修改如下:

 anchorSmoothScroll.scrollTo(elementId, speed);

元素是滚动到的强制属性,速度是可选的,默认值是20(和以前一样)。

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

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

只需将 smoothScroll模块作为一个依赖项包含进来,并像下面这样使用它:

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

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

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

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

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

Alan 谢谢,如果有人感兴趣的话,我是按照 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);
}
}


}


};


};


})();

我不知道如何动画 $anchorScroll。以下是我如何在我的项目:

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

And the JS function:

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;
}

我们可以使用带有 Directive 的 JQuery 和 Javascript 在单击锚标记时滚动到特定的 div。

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

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