做项目的时候有一个页面,其上方是总的菜单切换tab,下方是用iframe嵌套的子页面,这个子页面上方是一个多标签的菜单,下方是每个标签对应的内容,每块内容以表格的形式呈现。该页面主要的功能是,点击标签,页面滚动到相应的内容块。就是锚点定位。锚点定位实现的思路很简单,给每个标签添加onclick函数,参数传入对应的内容块的id,然后通过jquery的offset()得到该块的offset().top,即元素相对于文档偏移的高度,s=offset().top。最后关键代码:
$("html,body").animate({scrollTop:s},1000);
使用animate函数将scrollTop的高度设置为偏移的高度(一般情况下需要根据实际情况加或减去一定高度使定位更精准),设置时间为1000毫秒,可以使其平滑地滚动不至于很突然。
注意:刚开始锚点定位的javascript代码我是放在本页面的,无法实现,忽略了iframe嵌套的问题。然后我把代码转移到父页面,在本页面调用,可以很好地实现。
这之后有一个问题,点击标签页面滚动,标签菜单也随之滚上去看不见了,我们想要的效果是菜单随着屏幕滚动一定距离后可以固定在浏览器顶部,使我们还想查看其他标签的内容时,不用很麻烦地再滑动鼠标,继续点击锚点定位即可,然后当滚动条滚动到页面上方,标签菜单又回到原来的位置。如果该页面就是一整个页面,这样的需求很好实现。直接通过判断滚动条的高度改变标签菜单div的属性:
position:fixed;
top:0px;
可是我要点击的标签菜单位于iframe中,单纯使用以上的样式,只是让其定位在子页面的最上方,而不是整个浏览器的最上方。刚开始想的是在父页面写一个和iframe中的标签菜单完全一样div先隐藏,然后通过浏览器滚动的高度控制其的显示。但存在的问题是,这个标签菜单是后台传到前台的list循环读取出来的,要在父页面得到这个list,就得在父页面走的后台方法里重新查询一遍这个标签list再传给前台(或者从子页面将list传到父页面再循环?这样试想过貌似无法实现),总之这样直接在父页面写个一样的菜单很麻烦,不可取。
然后就想到可以取得这个标签菜单的html,再添加到最上层的页面中。对就是这样,在这个iframe中:
//$("#tag").html()获取id为tag块儿的html然后添加到最上层页面中
$(top.document.body).append("<div id=\"tag-top\" class=\"tag\">"+$("#tag").html()+"</div>");
//先隐藏掉
$(top.document.body).find("#tag-top").css({"display":"none"});
再给该div添上position和top的属性:
#tag-top{
position: fixed;
top: 0px;
width: 1200px;
left: 5.5%;
}
在页面滚动监听的方法里(该方法在父页面中):
$(window).scroll(function(){
var scrollt = document.documentElement.scrollTop + document.body.scrollTop; //获取滚动后的高度
//通过高度判断切换子页面和上层页面的标签菜单的显示与否
if(scrollt >=351)
{
$(top.document.body).find("#tag-top").css({"display":"block"});
$("#preview-management").contents().find("#tag").css({"display":"none"});
}
else
{
$(top.document.body).find("tag-top").css({"display":"none"});
$("#preview-management").contents().find("#tag").css({"display":"block"});
}
}
高度条件351,我是通过计算标签菜单的上边框距离浏览器的高度所得。这样的效果就是,页面正好滑到标签菜单上方时,子页面的div隐藏,上层页面的div显示,再滑回去div又很听话地“躺”回了原处,平滑无跳动,用户体验好。
还需注意,这样是实现了将子iframe的div定位到浏览器最上方(实际上是障眼法),那点击append到顶层的div的标签是不是还能很好地锚点定位?当然可以,之前不是说锚点定位是从子iframe调用父页面的方法来实现的嘛,只需要保证两个函数名一样即可。如下:
在子页面中:
function pageScroll(obj)
{
window.parent.pageScroll(obj);
}
父页面中:
function pageScroll(obj)
{
var id = obj.getAttribute("href");
var scroll_top = $("#iframeId").contents().find(id).offset();
var s = scroll_top.top
$("html,body").animate({scrollTop:s},1000);
}
然后这个功能就差不多实现了,其余的就是一些样式的调整,点击子页面的div定位和点击top.doucment.body中的div定位的结果可能有些偏差,可以添加一个调整的高度,如下:
子页面中:
function pageScroll(obj,count)
{
var scrollHeight = $("#tag").height();
window.parent.pageScroll(obj,count,scrollHeight);
}
父页面中:
function pageScroll(obj,count,scrollHeight)
{
var id = obj.getAttribute("href");
var ajustHeight = $(top.document.body).find("#tag").height();
if(scrollHeight != undefined)
{
ajustHeight = scrollHeight;
}
var s = scroll_top.top+ajustHeight;
$("html,body").animate({scrollTop:s},1000);
}
大功告成。写着的时候就发现这个博客的编辑器上的菜单栏正是这样的效果,滚动条滑下来它固定到了浏览器最上方,滑上去又回到原位。跟我这篇博文所讲的效果一样,只是我的多了锚点定位。我写的时候过程还是挺曲折,代码很简单,就是实现的方式想了半天,毕竟只是个前端小菜鸟,最后想出来这样的实现方法,如果有更好的方法请大家赐教^_^。