首頁  >  文章  >  web前端  >  使用Sticky組件實現帶有sticky效果的tab導航和滾動導航的方法_javascript技巧

使用Sticky組件實現帶有sticky效果的tab導航和滾動導航的方法_javascript技巧

WBOY
WBOY原創
2016-05-16 15:10:081805瀏覽

sticky組件,通常應用於導航條或工具列,當網頁在某一區域滾動的時候,將導航條或工具列這類元素固定在頁面頂部或底部,方便用戶快速進行這類元素提供的操作。

在這篇文章Sticky組件的改進實現提供了一個改進版的sticky組件,並將演示效果應用到了自己的博客。有了類似sticky的這種簡單組件,我們就可以利用它來開發更豐富的效果,例如本文要介紹的tab導航和滾動導航。實作簡單,示範效果如下:

tab導覽(對應tab-sticky.html):

滾動導覽(對應nav-scroll-sticky.html):

1. tab導航的實作

tab導覽的需求是:在點擊導覽項目的時候,除了切換tab內容,還要控制滾動,將要顯示的tab內容置頂,並且要剛好顯示在sticky元素的下邊。由於demo是用bootstrap做的,bootstrap提供的tab元件非常簡單好用,我們可以在tab元件提供的shown.bs.tab的事件回調裡做滾動控制處理,所以這個效果實現起來比較容易:

<script>
var $target = $('#target');
new Sticky('#sticky', {
unStickyDistance: 60,
target: $target,
wait: 1,
isFixedWidth: false,
getStickyWidth: function($elem) {
return $elem.parent()[0].offsetWidth;
}
});
$('a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
window.scrollTo(0, $target[0].getBoundingClientRect().top + getPageScrollTop() + 1);
});
function getPageScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
}
</script>

html結構:


2. 滾動導航實現

捲動導覽相對麻煩一些,tab元件裡面,只會顯示與目前啟動的tab項目對應的tab內容,而捲動導覽裡面,要導覽的所有內容都是已經在頁面中渲染完畢的,它的需求是:

1)點擊導覽項目的時候,控制頁面滾動,自動將與點擊的導航項目對應的內容置頂顯示,並且要剛好顯示在sticky元素的下邊;

2)頁面捲動的時候,根據目前顯示的導覽內容自動為對應的導覽項目新增active樣式。

儘管聽起來複雜,但是demo中的實作還是比較容易:

<script>
var $sticky = $('#sticky');
var $target = $('#target');
new Sticky($sticky, {
unStickyDistance: 60,
target: $target,
wait: 1,
isFixedWidth: false,
getStickyWidth: function ($elem) {
return $elem.parent()[0].offsetWidth;
}
});
var offsetTop = 60;
//实现点击tab项自动滚动到导航内容的效果
$sticky.on('click', 'a', function (e) {
e.preventDefault();
var $this = $(e.currentTarget);
var $parent = $this.parent();
if($parent.hasClass('active')) return;
$sticky.find('li.active').removeClass('active');
$parent.addClass('active');
var target = $this.data('target') || $this.attr('href');
var $target = $(target);
window.scrollTo(0, Math.floor($target[0].getBoundingClientRect().top) + getPageScrollTop() - offsetTop);
});
/**
* Math.floor是解决rect.top或rect.bottom带小数问题
*/
//实现滚动时根据当前显示的导航内容自动给相应的导航项添加active样式
$(window).scroll(throttle(function(){
var $curItem = $sticky.find('a').filter('[href=' + getCurTarget() + ']');
var $parent = $curItem.parent();
if($parent.hasClass('active')) return;
//最后的blur是为了去掉:active及:focus伪类的样式
$sticky.find('li.active').removeClass('active').find('a').trigger('blur');
$parent.addClass('active');
},1));
//获取当前显示的导航内容元素的id
function getCurTarget() {
for(var targets = ['#First', '#Second', '#Third'], i = 0, l = targets.length; i < l; i++) {
var curRect = $(targets[i])[0].getBoundingClientRect();
if(Math.floor(curRect.top) <= offsetTop && Math.floor(curRect.bottom) > offsetTop) {
return targets[i];
}
}
return targets[0];
}
function getPageScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
}
//这个函数在实际工作中是应该抽出来的,否则sticky.js里面还有一份重复的
function throttle(func, wait) {
var timer = null;
return function () {
var self = this, args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
return typeof func === 'function' && func.apply(self, args);
}, wait);
}
}
</script>

html結構:


3. 總結

本文結合sticky組件,提供了2種導航效果實現,相容於IE9+,firefox以及chrome,有興趣下載源碼再去詳細了解。在實作tab導覽的時候,因為有bs的tab元件所以實現起來非常容易,也沒有必要把sticky跟tab組件再封裝起來形成一個新元件,畢竟效果的實作程式碼已經比較簡單了。在實現滾動導航的時候,因為沒有用tab組件,所以滾動導航的那兩個需求點都是單獨實現的,在實際情況中,這兩個功能可以封裝成2個獨立的組件或者1個組件,這樣就能把實作程式碼寫的像tab導航那麼簡單,不過本文沒有再深入去介紹這兩個元件的寫法,因為這不是本文主要想介紹的內容,雖然我很想這麼做,後續肯定會再寫部落格來介紹這兩個組件,簡單的東西不造一下輪子,簡直是浪費機會。在實現這兩個效果的時候,也有2點收穫:

1)firefox以及IE,先讓網頁,然後再刷新,雖然網頁還會顯示在刷新的位置,但是不會觸發scroll事件,所以今後做scroll相關的元件,一定在元件初始化的時候主動掉一次scroll相關的回呼;

2)getBoundingClientRect回傳的rect物件相關的值,在IE和firefox下,都可能是小數,例如60.2222299999,這樣的數,在進行判斷的時候可能會跟預期情況不符,導致一些意外的BUG,如果不是特別嚴謹的話,可以用Math.floor對這些值進行取整,然後再用來計算或判斷。例如滾動導航實作中,rect.top的值60.2222299999,offsetTop的值是60,期望是curRect.top

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn