使用Sticky組件實(shí)現(xiàn)帶sticky效果的tab導(dǎo)航和滾動(dòng)導(dǎo)航的方法
sticky組件,通常應(yīng)用于導(dǎo)航條或者工具欄,當(dāng)網(wǎng)頁(yè)在某一區(qū)域滾動(dòng)的時(shí)候,將導(dǎo)航條或工具欄這類(lèi)元素固定在頁(yè)面頂部或底部,方便用戶快速進(jìn)行這類(lèi)元素提供的操作。
在這篇文章Sticky組件的改進(jìn)實(shí)現(xiàn)提供了一個(gè)改進(jìn)版的sticky組件,并將演示效果應(yīng)用到了自己的博客。有了類(lèi)似sticky的這種簡(jiǎn)單組件,我們就可以在利用它開(kāi)發(fā)更豐富的效果,比如本文要介紹的tab導(dǎo)航和滾動(dòng)導(dǎo)航。實(shí)現(xiàn)簡(jiǎn)單,演示效果如下:
tab導(dǎo)航(對(duì)應(yīng)tab-sticky.html):
滾動(dòng)導(dǎo)航(對(duì)應(yīng)nav-scroll-sticky.html):
1. tab導(dǎo)航的實(shí)現(xiàn)
tab導(dǎo)航的需求是:在點(diǎn)擊導(dǎo)航項(xiàng)的時(shí)候,除了切換tab內(nèi)容,還要控制滾動(dòng),將要顯示的tab內(nèi)容置頂,并且要?jiǎng)偤蔑@示在sticky元素的下邊。由于demo是用bootstrap做的,bootstrap提供的tab組件非常簡(jiǎn)單好用,我們可以在tab組件提供的shown.bs.tab的事件回調(diào)里做滾動(dòng)控制處理,所以這個(gè)效果實(shí)現(xiàn)起來(lái)比較容易:
<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結(jié)構(gòu):
2. 滾動(dòng)導(dǎo)航實(shí)現(xiàn)
滾動(dòng)導(dǎo)航相對(duì)麻煩一些,tab組件里面,只會(huì)顯示與當(dāng)前激活的tab項(xiàng)對(duì)應(yīng)的tab內(nèi)容,而滾動(dòng)導(dǎo)航里面,要導(dǎo)航的所有內(nèi)容都是已經(jīng)在頁(yè)面中渲染完畢的,它的需求是:
1)點(diǎn)擊導(dǎo)航項(xiàng)的時(shí)候,控制頁(yè)面滾動(dòng),自動(dòng)將與點(diǎn)擊的導(dǎo)航項(xiàng)對(duì)應(yīng)的內(nèi)容置頂顯示,并且要?jiǎng)偤蔑@示在sticky元素的下邊;
2)頁(yè)面滾動(dòng)的時(shí)候,根據(jù)當(dāng)前顯示的導(dǎo)航內(nèi)容自動(dòng)給相應(yīng)的導(dǎo)航項(xiàng)添加active樣式。
盡管聽(tīng)起來(lái)復(fù)雜,但是demo中的實(shí)現(xiàn)還是比較容易:
<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; //實(shí)現(xiàn)點(diǎn)擊tab項(xiàng)自動(dòng)滾動(dòng)到導(dǎo)航內(nèi)容的效果 $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帶小數(shù)問(wèn)題 */ //實(shí)現(xiàn)滾動(dòng)時(shí)根據(jù)當(dāng)前顯示的導(dǎo)航內(nèi)容自動(dòng)給相應(yīng)的導(dǎo)航項(xiàng)添加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偽類(lèi)的樣式 $sticky.find('li.active').removeClass('active').find('a').trigger('blur'); $parent.addClass('active'); },1)); //獲取當(dāng)前顯示的導(dǎo)航內(nèi)容元素的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; } //這個(gè)函數(shù)在實(shí)際工作中是應(yīng)該抽出來(lái)的,否則sticky.js里面還有一份重復(fù)的 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結(jié)構(gòu):
3. 總結(jié)
本文結(jié)合sticky組件,提供了2種導(dǎo)航效果實(shí)現(xiàn),兼容IE9+,firefox以及chrome,感興趣可以下載源碼再去詳細(xì)了解。在實(shí)現(xiàn)tab導(dǎo)航的時(shí)候,因?yàn)橛衎s的tab組件所以實(shí)現(xiàn)起來(lái)非常容易,也沒(méi)有必要把sticky跟tab組件再封裝起來(lái)形成一個(gè)新組件,畢竟效果的實(shí)現(xiàn)代碼已經(jīng)比較簡(jiǎn)單了。在實(shí)現(xiàn)滾動(dòng)導(dǎo)航的時(shí)候,因?yàn)闆](méi)有用tab組件,所以滾動(dòng)導(dǎo)航的那兩個(gè)需求點(diǎn)都是單獨(dú)實(shí)現(xiàn)的,在實(shí)際情況中,這兩個(gè)功能可以封裝成2個(gè)獨(dú)立的組件或者1個(gè)組件,這樣就能把實(shí)現(xiàn)代碼寫(xiě)的像tab導(dǎo)航那樣簡(jiǎn)單,不過(guò)本文沒(méi)有再深入去介紹這兩個(gè)組件的寫(xiě)法,因?yàn)檫@不是本文主要想介紹的內(nèi)容,雖然我很想這么做,后續(xù)肯定會(huì)再寫(xiě)博客來(lái)介紹這兩個(gè)組件,簡(jiǎn)單的東西不造一下輪子,簡(jiǎn)直是浪費(fèi)機(jī)會(huì)。在實(shí)現(xiàn)這兩個(gè)效果的時(shí)候,也有2點(diǎn)收獲:
1)firefox以及IE,先讓網(wǎng)頁(yè),然后再刷新,雖然網(wǎng)頁(yè)還會(huì)顯示在刷新的位置,但是不會(huì)觸發(fā)scroll事件,所以今后做scroll相關(guān)的組件,一定在組件初始化的時(shí)候主動(dòng)掉一次scroll相關(guān)的回調(diào);
2)getBoundingClientRect返回的rect對(duì)象相關(guān)的值,在IE和firefox下,都可能是小數(shù),比如60.2222299999,這樣的數(shù),在進(jìn)行判斷的時(shí)候可能會(huì)跟預(yù)期情況不符,導(dǎo)致一些意外的BUG,如果不是特別嚴(yán)謹(jǐn)?shù)脑挘梢杂肕ath.floor對(duì)這些值進(jìn)行取整,然后再用來(lái)計(jì)算或者判斷。比如滾動(dòng)導(dǎo)航實(shí)現(xiàn)中,rect.top的值60.2222299999,offsetTop的值是60,期望是curRect.top <= offsetTop這個(gè)條件能夠成立,因?yàn)樾?shù)的原因,所以它不成立。
- Firefox getBoxObjectFor getBoundingClientRect聯(lián)系
- 各種常用瀏覽器getBoundingClientRect的解析
- javascript getBoundingClientRect() 來(lái)獲取頁(yè)面元素的位置的代碼[修正版]
- javascript 獲取元素位置的快速方法 getBoundingClientRect()
- js getBoundingClientRect() 來(lái)獲取頁(yè)面元素的位置
- 獲取元素距離瀏覽器周邊的位置的方法getBoundingClientRect
- 淺談Sticky組件的改進(jìn)實(shí)現(xiàn)
- 使用getBoundingClientRect方法實(shí)現(xiàn)簡(jiǎn)潔的sticky組件的方法
相關(guān)文章
JavaScript的類(lèi)型、值和變量小結(jié)
這篇文章主要介紹了JavaScript的類(lèi)型、值和變量小結(jié)的相關(guān)資料,需要的朋友可以參考下2015-07-07JavaScript實(shí)現(xiàn)擦玻璃效果分析鼠標(biāo)移動(dòng)響應(yīng)時(shí)間粒度問(wèn)題
這篇文章主要為大家介紹了JavaScript實(shí)現(xiàn)擦玻璃效果分析鼠標(biāo)移動(dòng)響應(yīng)時(shí)間粒度問(wèn)題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10JavaScript Typescript基礎(chǔ)使用教程
TypeScript是Microsoft(微軟)開(kāi)發(fā)的一種開(kāi)源編程語(yǔ)言,它充分利用了JavaScript原有的對(duì)象模型,并在此基礎(chǔ)上進(jìn)行了擴(kuò)充,TypeScript設(shè)計(jì)目標(biāo)是開(kāi)發(fā)大型應(yīng)用,它可以編譯成純JavaScript,編譯出來(lái)的JavaScript可以運(yùn)行在任何一種JS運(yùn)行環(huán)境中2022-12-12利用JavaScript中的高階函數(shù)和閉包實(shí)現(xiàn)命令模式
命令模式提供了一種優(yōu)雅的解決方案,使得我們能夠靈活地封裝和管理代碼操作,所以本文將為大家介紹命令模式的概念、應(yīng)用場(chǎng)景以及在JavaScript中的實(shí)現(xiàn)方式,需要的可以參考一下2023-06-06js 判斷圖片是否加載完以及實(shí)現(xiàn)圖片的預(yù)下載
這篇文章主要介紹了js 判斷圖片是否加載完以及實(shí)現(xiàn)圖片的預(yù)下載,需要的朋友可以參考下2014-08-08