在 AngularJS 中起作用

我正在尝试快速导航以正确工作。它在侧面漂浮着。当他们点击一个链接时,它会将他们带到页面上的 ID。我在跟踪这个 来自树屋的向导。 这是我的滚动条:

$("#quickNav a").click(function(){
var quickNavId = $(this).attr("href");
$("html, body").animate({scrollTop: $(location).offset().top}, "slow");
return false;
});

我最初把它放在 </body>之前。但是我似乎遇到了一种竞争状态,在快速导航编译之前,它就已经启动了(它有一个 ng-hide放置在上面,不确定是否是它引起的——但是它在 DOM 中)。

如果我在控制台中运行这段代码,那么滚动将按预期工作。

我认为把这个转移到控制器中会更有效——或者更有可能是在指令范围内。但是我没有运气做到这一点。我怎样才能让这段代码与 AngularJS 一起工作?

154448 次浏览

下面是一个简单的指令,它会在单击时滚动到一个元素:

myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm) {
$elm.on('click', function() {
$("body").animate({scrollTop: $elm.offset().top}, "slow");
});
}
}
});

演示: http://plnkr.co/edit/yz1EHB8ad3C59N6PzdCD?p=preview

有关创建指令的帮助,请查看 http://egghead.io上的视频,从 # 10“第一个指令”开始。

编辑 : 要让它滚动到 href 指定的特定元素,只需选中 attrs.href

myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm, attrs) {
var idToScroll = attrs.href;
$elm.on('click', function() {
var $target;
if (idToScroll) {
$target = $(idToScroll);
} else {
$target = $elm;
}
$("body").animate({scrollTop: $target.offset().top}, "slow");
});
}
}
});

然后您可以像这样使用它: <div scroll-on-click></div>滚动到单击的元素。或者 <a scroll-on-click href="#element-id"></div>,用 id 滚动到元素。

谢谢安迪的例子,这是非常有帮助的。我结束了实施一个略有不同的策略,因为我正在开发一个单页滚动条,并不希望 Angular 刷新时使用 hashbang URL。我还想保留浏览器的后退/前进操作。

我没有使用指令和散列,而是使用 $scope。$watch on the $location. search,and getting the target from there.这给了一个很好的干净的锚标记

<a ng-href="#/?scroll=myElement">My element</a>

我将手表代码链接到 app.js 中的 my 模块声明,如下所示:

.run(function($location, $rootScope) {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0;
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
})

上面代码的警告是,如果您通过 URL 直接从不同的路由访问,DOM 可能无法及时加载到 jQuery 的 $target.offet ()调用中。解决方案是将此代码嵌套在 $viewContentLoadedwatcher 中。最终代码如下所示:

.run(function($location, $rootScope) {
$rootScope.$on('$viewContentLoaded', function() {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
var scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
});
})

使用 Chrome 和 FF 进行测试

如果你想使用它,这是一个更好的指令:

您可以滚动到页面中的任何元素:

.directive('scrollToItem', function() {
return {
restrict: 'A',
scope: {
scrollTo: "@"
},
link: function(scope, $elm,attr) {


$elm.on('click', function() {
$('html,body').animate({scrollTop: $(scope.scrollTo).offset().top }, "slow");
});
}
}})

用法(例如点击 div‘ back-to-top’将滚动到 id 滚动到 top) :

<a id="top-scroll" name="top"></a>
<div class="back-to-top" scroll-to-item scroll-to="#top-scroll">

它也支持 chrome,firefox,safari 和 IE 的 html,body 元素。

为了在滚动容器(固定 DIV)中对特定元素进行动画处理

/*
@param Container(DIV) that needs to be scrolled, ID or Div of the anchor element that should be scrolled to
Scrolls to a specific element in the div container
*/
this.scrollTo = function(container, anchor) {
var element = angular.element(anchor);
angular.element(container).animate({scrollTop: element.offset().top}, "slow");
}

那么 角度旋转呢? 它是主动维护的,并且不依赖于 jQuery。

一个角度解决方案使用 $anchorScroll从现在存档的 作者: Ben Lesh,这也在一些细节转载在 这么回答,他贡献(包括重写如何在一个路由内做到这一点) :

app.controller('MainCtrl', function($scope, $location, $anchorScroll) {
var i = 1;
  

$scope.items = [{ id: 1, name: 'Item 1' }];
  

$scope.addItem = function (){
i++;
//add the item.
$scope.items.push({ id: i, name: 'Item ' + i});
//now scroll to it.
$location.hash('item' + i);
$anchorScroll();
};
});

下面是提供这个解决方案的博客: http://plnkr.co/edit/xi2r8wP6ZhQpmJrBj1jM?p=preview

值得注意的是,该柱塞上的模板包括这一点,它设置了 id,您正在使用 $anchorScroll滚动到:

<li ng-repeat="item in items"
id="item\{\{item.id}}"
>\{\{item.name}</li>

如果你喜欢纯 javascript 解决方案,这里有一个:

使用父容器 ID 和目标滚动标识在代码中调用 runScroll:

function runScroll(parentDivId,targetID) {
var longdiv;
longdiv = document.querySelector("#" + parentDivId);
var div3pos = document.getElementById(targetID).offsetTop;
scrollTo(longdiv, div3pos, 600);
}




function scrollTo(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;


setTimeout(function () {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop == to) return;
scrollTo(element, to, duration - 10);
}, 10);
}

参考资料: 跨浏览器 JavaScript (不是 jQuery...)滚动到顶部动画

我用了 Andrew Joslin 的答案,效果很好,但是触发了角度路线的改变,这让我看起来有点神经质。如果你想避免触发路线改变,

myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm, attrs) {
var idToScroll = attrs.href;
$elm.on('click', function(event) {
event.preventDefault();
var $target;
if (idToScroll) {
$target = $(idToScroll);
} else {
$target = $elm;
}
$("body").animate({scrollTop: $target.offset().top}, "slow");
return false;
});
}
}
});

另一个建议。一个指令与选择器。

HTML:

<button type="button" scroll-to="#catalogSection">Scroll To</button>

角度:

app.directive('scrollTo', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.on('click', function () {


var target = $(attrs.scrollTo);
if (target.length > 0) {
$('html, body').animate({
scrollTop: target.offset().top
});
}
});
}
}
});

还要注意 $锚滚动

非常清楚的答案,只使用 ANGULARJS,没有任何 JQUERY 依赖

在你的 html 中的某个地方的底部 <back-top>some text</back-top>

在你的超文本标记语言的顶部 <div id="top"></div>的某个地方

在你的文件夹里:

/**
* @ngdoc directive
* @name APP.directive:backTop
<pre>
<back-top></back-top>
</pre>
*/




angular
.module('APP')
.directive('backTop', ['$location', '$anchorScroll' ,function($location, $anchorScroll) {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<span class=\'btn btn-mute pull-right\'><i class=\'glyphicon glyphicon-chevron-up\'></i><ng-transclude></ng-transclude></span>',
scope: {
},
link: function(scope, element) {
element.on('click', function(event) {
$anchorScroll(['top']);
});
}
};
}]);

通过使用元素的 ID 滚动到目标 div

指令(角度1)

angular.module("App") // Module Name
.directive('scrollOnClick', function () {
return {
restrict: 'A',
scope: {
scrollTo: "@"
},
link: function (scope, $elm, attrs) {
//var idToScroll = attrs.href;
$elm.on('click', function () {
$('html,body').animate({ scrollTop: $(scope.scrollTo).offset().top }, "slow");
});
}
}
});

HTML 代码

<!-- Click to scroll -->
<a scroll-on-click scroll-to="#scheduleDiv">Click here to Scroll to Div With Id ""</a>




<!-- scrollable / target div -->
<div id="scheduleDiv">Test scrolling ... You are able to view me on click of above anchor tag.</div>