什么是异步移动?当可视区域下移(即滚动条下移)时,左侧的侧边栏会同时向下移动,这样无论什么时候都不会出现侧边栏留白的现象。同时还可以发现,当可是区域在页面最上方时,侧边栏的顶部靠近浏览器顶部;但当显示区域在页面底部时,侧边栏的底部正好完全显示出来。这一点也在代码中有所体现。
首先要获得浏览器相关参数
function getPagePos() { var st, sl, sw, sh, cw, ch; if (document.documentElement && document.documentElement.scrollTop) { st = document.documentElement.scrollTop; sl = document.documentElement.scrollLeft; sw = document.documentElement.scrollWidth; sh = document.documentElement.scrollHeight; } else if (document.body) { st = document.body.scrollTop; sl = document.body.scrollLeft; sw = document.body.scrollWidth; sh = document.body.scrollHeight; } cw = document.documentElement.clientWidth; ch = document.documentElement.clientHeight; return { scrollTop : st, scrollLeft: sl, scrollWidth: sw, scrollHeight: sh, clientWidth : cw, clientHeight : ch }; }
返回值分别为:
scrollTop:垂直滚动条位置
scrollLeft:水平滚动条位置
scrollHeight:页面总高度
scrollWidth:页面总宽度
scrollWidth:可见区域高度
clientWidth:可见区域宽度
这些参数对侧边栏位置的计算起到重要的作用。Simoll.us页面布局(div的id)如下:
为了实现侧边栏的位移,我们可以用JavaScript改变CSS中的padding-top值(使用jQuery库),代码如下:
varnowPt = 0; varaimPt = 0; varasSteps = 12; varpagePos; varminDeltaPt = 3; functionasyncSidebar() { if (Math.abs(aimPt - nowPt) < 1) { setTimeout(function(){asyncSidebar();}, 500); } else { vardeltaPt = (aimPt - nowPt) / asSteps; if (Math.abs(deltaPt) < minDeltaPt) { if (deltaPt > 0) { deltaPt = minDeltaPt; } else { deltaPt = -minDeltaPt; } } vargotoPt = nowPt + deltaPt; $("#sidebar").animate({paddingTop:gotoPt + "px"}, 1000 / asSteps * 0.95); nowPt = gotoPt; setTimeout(function(){asyncSidebar();}, 1000 / asSteps); } } functionasyncSidebarUpdate() { varpagePos = getPagePos(); aimPt = ($("#content").height() - $("#sidebar").height()) * pagePos.scrollTop / (pagePos.scrollHeight - pagePos.clientHeight); } $(function() { window.onscroll = asyncSidebarUpdate; asyncSidebar(); });
在这段代码中,我们设置window.onscroll监听器来更新滚动条位置,用asyncSidebar函数更新侧边栏CSS。这样的好处是便于控制侧边栏的重绘,不因onscroll监听器的调用导致卡顿。
在重绘CSS的代码中,将单帧时间乘以常数0.95,避免由于CPU计算能力导致jQuery队列过长(但改方法并未完全解决此问题,希望能找到更好的解决办法)
如果要移植这段代码非常简单,只需要根据主题修改各div的id即可。