Javascript ScrollTo在AngularJS中运行
我在试着让导航系统正常工作。它漂浮在一边。当他们点击一个链接时,它会将他们带到页面上的那个ID。我正在关注这个。 这是我为滚动所做的:Javascript ScrollTo在AngularJS中运行,javascript,jquery,angularjs,scroll,anchor,Javascript,Jquery,Angularjs,Scroll,Anchor,我在试着让导航系统正常工作。它漂浮在一边。当他们点击一个链接时,它会将他们带到页面上的那个ID。我正在关注这个。 这是我为滚动所做的: $("#quickNav a").click(function(){ var quickNavId = $(this).attr("href"); $("html, body").animate({scrollTop: $(location).offset().top}, "slow"); return false; }); 我最初把它
$("#quickNav a").click(function(){
var quickNavId = $(this).attr("href");
$("html, body").animate({scrollTop: $(location).offset().top}, "slow");
return false;
});
我最初把它放在
前面。但我似乎遇到了一种竞争条件,在编译quickNav之前就触发了这种情况(它有一个ng hide
,不确定这是否是导致它的原因,但它在DOM中)
如果我在控制台中运行该代码块,那么滚动将按预期工作
我认为将其移动到控制器中会更有效——或者更可能是在指令中。但我没有运气做到这一点如何让这段代码与AngularJS一起使用?这里有一个简单的指令,单击后将滚动到一个元素:
myApp.directive('scrollOnClick', function() {
return {
restrict: 'A',
link: function(scope, $elm) {
$elm.on('click', function() {
$("body").animate({scrollTop: $elm.offset().top}, "slow");
});
}
}
});
演示:
有关创建指令的帮助,请查看位于的视频,从#10“第一个指令”开始
编辑:要使其滚动到a 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");
});
}
}
});
然后您可以这样使用它:
滚动到单击的元素。或者
滚动到id为的元素。感谢Andy提供的示例,这非常有用。我最终实现了一个稍微不同的策略,因为我正在开发一个单页滚动,并且不希望在使用hashbang URL时刷新。我还希望保留浏览器的后退/前进操作
我没有使用指令和散列,而是在$location.search上使用$scope.$watch,并从那里获取目标。这提供了一个非常干净的锚标签
我将watch代码链接到app.js中的my module声明,如下所示:
.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.offset()调用。解决方案是将此代码嵌套在$viewContentLoaded watcher中。最终代码如下所示:
.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“返回顶部”将滚动至id滚动顶部):
chrome、firefox、safari和IE也支持它,因为html、body元素都支持它。以便在滚动容器中为特定元素设置动画(固定DIV)
那么,它是主动维护的,并且不依赖于jQuery。一个角度解决方案,使用
$anchorScroll
从一个现已存档的文件中获取,该文件也在他的贡献中进行了一些详细的复制(包括如何在路由中执行此操作的重写):
以下是提供此解决方案的博客中的plunker:
需要注意的重要一点是,该plunker上的模板包括以下内容,它设置了您使用$anchorScroll
滚动到的id
:
<li ng-repeat="item in items"
id="item{{item.id}}"
>{{item.name}</li>
{{item.name}
如果您喜欢纯javascript解决方案,这里有一个: 使用父容器id和目标滚动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);
}
函数runScroll(parentDivId,targetID){
var longdiv;
longdiv=document.querySelector(“#”+parentDivId);
var div3pos=document.getElementById(targetID).offsetTop;
scrollTo(longdiv,div3pos,600);
}
函数滚动到(元素、到、持续时间){
如果(持续时间<0)返回;
var差异=到-element.scrollTop;
var perTick=差异/持续时间*10;
setTimeout(函数(){
element.scrollTop=element.scrollTop+perTick;
if(element.scrollTop==to)返回;
滚动至(元素,至,持续时间-10);
}, 10);
}
参考资料:我使用了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:
另外请注意,答案非常清楚,只使用ANGULARJS,没有任何JQUERY依赖 在html的底部某处
一些文本
在html的顶部某处
在您的js中:
/**
* @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']);
});
}
};
}]);
/**
*@ngdoc指令
*@name APP.directive:backTop
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");
});
}
}
});
*/
有棱角的
.module('应用程序')
.directive('backTop',['$location','$anchorScroll',function($location,$anchorScroll){
返回{
限制:'E',
替换:正确,
是的,
模板:“”,
范围:{
},
链接:功能(范围、元素){
元素上('click',函数(事件){
$anchorScroll(['top']);
});
}
};
}]);
使用元素的ID滚动到目标div
指令(角度1)
HTML代码
单击此处滚动至Id为“”的Div
测试滚动…点击上面的锚标签,你就可以看到我了。
感谢您对基本指令的帮助。我已经做了一些非常基本的指令。我不确定如何访问quicknav中的href(使用指令)使其进行锚定链接。我最终从编辑中删除了几行代码(主要是if
块)这将用于滚动到单击的元素(如您在plunker中演示的)正确吗?只是为了使其更模块化?任何人都可以使用这一功能并绕过iOS的“功能”,该功能导致必须双击才能触发“单击”@rnrnverdies如果您将$(“body”)更改为$(“body,html”),它在firefox上确实有效为了获得最佳的跨浏览器支持,您应该使用$(“html,body”).animate()。更新了我的答案为什么我需要两个指令而不是一个滚动到item=“.selector”
?
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;
});
}
}
});
<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
});
}
});
}
}
});
/**
* @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']);
});
}
};
}]);
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");
});
}
}
});
<!-- 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>