什麼是異步移動?當可視區域下移(即滾動條下移)時,左側的側邊欄會同時向下移動,這樣無論什麼時候都不會出現側邊欄留白的現象。同時還可以發現,當可是區域在頁面最上方時,側邊欄的頂部靠近瀏覽器頂部;但當顯示區域在頁面底部時,側邊欄的底部正好完全顯示出來。這一點也在代碼中有所體現。
首先要獲得瀏覽器相關參數
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即可。