在我的AngularJS应用程序中,我有一个包含多个子部分的页面。所有这些子部分都在同一页面上,并且是同一模板的一部分。但是我想通过它自己的URL访问每个部分,如果它匹配,它将向下滚动到正确的部分。
我已将状态设置为:
.state('about', {
url: "/about",
templateUrl: "partials/about.html",
})
.state('about.team', {
url: "/about/team",
templateUrl: "partials/about.html"
})
.state('about.office', {
url: "/about/office",
templateUrl: "partials/about.html"
})
.state('about.other', {
url: "/about/other",
templateUrl: "partials/about.html"
});
在about页面上我有一个菜单:
<div class="menu">
<a ui-sref-active="selected"
ui-sref="about.team">The Team</a>
<a ui-sref-active="selected"
ui-sref="about.office">The Office</a>
<a ui-sref-active="selected"
ui-sref="about.other">Other</a>
</div>
此菜单固定在底部,当用户点击链接或通过地址栏直接访问网址时,它应滚动到该部分(更新需要匹配的网址)。
但是我不知道该怎么做(通过Angular)。总结一下:
页面的HTML看起来像:http://pastebin.com/Q60FWtL7
您可以在此处查看该应用:http://dev.driz.co.uk/AngularPage/app/#/about
对于类似的事情(https://devart.withgoogle.com/#/about/your-opportunity)的示例,您可以看到它根据网页加载后的网址向下滚动到正确的部分...并且不使用哈希但是实际网址
答案 0 :(得分:2)
您可以尝试使用此方法创建一个触发单击滚动的指令。 您可以将此指令作为属性添加到链接中。其中sref属性将是目标div的id。
app.directive('scrollTo', function() {
return {
link: function(scope, element, attrs) {
element.bind('click', function() {
var divPosition = $(attrs.sRef).offset();
$('html, body').animate({
scrollTop: divPosition.top
}, "slow");
});
}
};
});
答案 1 :(得分:2)
.state('about.office', {
url: "/about/office"
,templateUrl: "partials/about.html"
,scrollToId = "divAboutOffice";
})
然后,当您注入$ state服务时,您的控制器可以访问此数据。
$('html, body').animate({
scrollTop: $($state.current.scrollToId).offset().top
}, "slow");
假设您在HTML中添加了id="divAboutOffice"
。 (并假设我的jQuery引用是正确的;我不使用jquery所以我不确定。)
根据您的需要,您可以在animate()
中将$on()
换成其中一个事件:$locationChangeSuccess)
,$routeChangeSuccess
或$stateChangeSuccess
另外:您不必像我一样使用&#34; id&#34; - 如果您真的想按属性搜索元素,可以利用现有的ui-sref
。在您看来匹配$state.current.name
答案 2 :(得分:0)
我将使用window.scrollTo或jquery scrollTo插件创建一个scrollTo指令。
实施例: Angular directive to scroll to a given item 使用window.scrollTo
Jquery scrollTo插件:
https://github.com/flesler/jquery.localScroll
https://github.com/flesler/jquery.scrollTo
在页面加载时,滚动到由标签或任何其他url参数定义的视图。例: www.sample.com#aboutUs或www.samplecom?view = aboutUs
答案 3 :(得分:0)
1. bind to "scroll" events,
2. compare if I reached the position of each headers, using "element.offset().top"
(在将此标题作为指令之后。(我应该将标题作为指令,检查如何从ngtutorial.com/learn/scope生成目录)
3. update location.url()
关于加载(我更喜欢使用hashtags,因为我可以使用$ anchorScroll()或使用.when()),无论如何加载时更新的示例是:
1. http://ngtutorial.com/guide.html#/learn-filter.html
2. http://ngtutorial.com/learn/route.html#/_tblcontents_5
如果您不喜欢主题标签,则可以解析location.url()
答案 4 :(得分:0)
我在自己的应用程序中使用https://github.com/durated/angular-scroll进行滚动控制(并滚动间谍),而不是使用locationHash。我自己没有尝试过这个解决方案,但我认为它会起作用。
您需要在重要的div上声明某种项ID(作为您滚动的位置)。
然后你可以使用url / about /:locale声明一个状态“about.stately”(在ui-router stateParams中不必是整数)。然后在控制器中约。最后,你可以(从角度滚动自述文件):
var someElement = angular.element(document.getElementById('some-id'));
$document.scrollToElement(someElement, offset, duration);
根据控制器中的$ stateParams.locale选择要滚动到的元素。小心等到你的所有子指令和东西加载后 - 你可能需要$ evalAsync才能使它正常工作。但我认为这就是它的主旨。
答案 5 :(得分:0)
这就是我现在所尝试的:
var scrolled = false;
var listenToScroll = false;
$('.subsection').each(function(i) {
var position = $(this).position();
$(this).scrollspy({
min: position.top,
max: position.top + $(this).outerHeight(),
onEnter: function(element, position) {
if(element.id){
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about.'+element.id);
}
} else {
if(listenToScroll) {
scrolled = true;
$state.transitionTo('about');
}
}
}
});
});
$scope.startListenToScroll = function() {
listenToScroll = true;
}
$scope.stopListenToScroll = function(){
listenToScroll = false;
}
$scope.$on('$stateChangeStart', function(){
$scope.stopListenToScroll();
});
$scope.$on('$stateChangeSuccess', function(){
console.log(scrolled);
if( !scrolled ) {
var link = $state.current.name.split('.');
if(link.length>1){
var divPosition = $( '#' + link[1] ).offset();
$('body').stop(true,true).animate({ scrollTop: divPosition.top }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
} else {
$('body').stop(true,true).animate({ scrollTop: 0 }, "fast", function(){
$scope.startListenToScroll();
scrolled = false;
});
}
} else {
$scope.startListenToScroll();
scrolled = false;
}
});
因此,您可以看到我收听stateChangeSuccess而不是点击!这样我就可以挂钩任何状态更改,无论它们是否被链接或浏览器历史记录按钮调用,并根据需要执行滚动。
一旦开始更改开始,我就会关闭scrollspy,以便滚动动画不会调用另一个状态更改(因为它可能会滚动其他部分创建虚假历史记录条目)。然后在动画完成后再次将其重新打开,这样我就可以再次收听滚动事件。
stateChangeSuccess在页面加载时触发,因此它处理任何URL粘贴。
我有一个名为scrolled
的变量,以便我可以跟踪状态更改是否是由用户滚动引起的。这是因为当用户滚动它们时,我不需要为scrollTop设置动画。
<强>思考吗
答案 6 :(得分:0)
你需要做的是在页面顶部创建一个指令,除了监视状态的ui-router,然后根据右边的锚点滚动。因此,您无需使用templateUrls,因为您要实现的是某种平滑。
答案 7 :(得分:-1)
// get the current path
var x=$location.path();
// say x='about/team'
//read the last tag and set scrollTo to the top offset of desired div
if(lasttag(x)==team){
scroll to top offset of TEAM div;
}
else if(lasttag(x)==office){
scroll to top offset of OFFICE div;
}