jquery跟隨屏幕滾動(dòng)效果的實(shí)現(xiàn)代碼
我們?cè)诤芏嗑W(wǎng)站看到,當(dāng)我們滾動(dòng)網(wǎng)頁(yè)時(shí),網(wǎng)頁(yè)內(nèi)的廣告或某個(gè)小區(qū)域并不會(huì)消失,而是浮動(dòng)在屏幕的某個(gè)地方,特別是一些局域廣告。那么這是怎么實(shí)現(xiàn)的呢?本文將引用烏徒幫的跟隨屏幕滾動(dòng)代碼,對(duì)此效果做詳解。
一、原始代碼
下面是烏徒幫的跟隨屏幕滾動(dòng)代碼,它的作用域?yàn)闉跬綆途W(wǎng)頁(yè)兩側(cè)的邊欄,以及雙擊屏幕后的右側(cè)隱藏欄。
var $catalogueOffsetTop = $('aside#catalogue').offset().top; var $archiveOffestTop = $('aside#archive').offset().top; var $archiveOffestLeft = $('aside#archive').offset().left; $(window).bind('scroll resize',function(){ // #right-area的跟隨屏幕滾動(dòng)效果 if($('#right-area').height() <= $(window).height()){ $('#right-area').stop(true,true).animate({'top': $(document).scrollTop() + 'px'},800); }else if($('#right-area').height() > $(window).height() && $('#right-area').height() < $(document).height()){ // 這段范圍內(nèi)是最關(guān)鍵的,允許滑動(dòng) if(($(document).scrollTop() + $(window).height()) <= $('#right-area').height()){ $('#right-area').stop(true,true).css('top','0'); }else if(($(document).scrollTop() + $(window).height()) < $(document).height()){ $right_top = $(document).scrollTop() + $(window).height() - $('#right-area').height(); $('#right-area').stop(true,true).animate({'top': $right_top + 'px'},800); }else{ $right_top = $(document).height() - $('#right-area').height(); $('#right-area').stop(true,true).css({'top': $right_top + 'px'}); //alert($(document).scrollTop() + $(window).height() - $(document).height()); } }else if($('#right-area').height() >= $(document).height()){ $('#right-area').height($(document).height()).stop(true,true).css({'overflow':'hidden','overflow-y':'scroll'}); } if($(document).scrollLeft() == 0){ // 只有在屏幕處于左側(cè)的時(shí)候才進(jìn)行下面的跟隨滾動(dòng),同時(shí)需要注意下面的if($(window).width() > 1024),是為了防止在小屏幕下還發(fā)生這種變化 // aside#catalogue的上下滑動(dòng) if($('aside#catalogue').outerHeight() < $(window).height()){ if($(document).scrollTop() <= $catalogueOffsetTop){ $('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); if($(window).width() > 1024)$('#main').css({'padding-left':'0'}); }else{ $('aside#catalogue').css({'position':'fixed','top':'0'}); if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); } }else if($('aside#catalogue').height() >= $(window).height() && $('aside#catalogue').outerHeight() < ($('footer').offset().top - $catalogueOffsetTop)){ if(($(document).scrollTop() + $(window).height()) <= ($('aside#catalogue').outerHeight() + $catalogueOffsetTop)){ $('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); if($(window).width() > 1024)$('#main').css({'padding-left':'0'}); }else if(($(document).scrollTop() + $(window).height()) < $('footer').offset().top){ $catalogue_top = $(window).height() - $('aside#catalogue').outerHeight() - 20; $('aside#catalogue').css({'position':'fixed','top': $catalogue_top + 'px'}); if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); }else{ $catalogue_top = $(window).height() - $('aside#catalogue').outerHeight() - 20 - ($(document).height() - $('footer').offset().top); $('aside#catalogue').css({'position':'fixed','top':$catalogue_top + 'px'}); if($(window).width() > 1024)$('#main').css({'padding-left':$('aside#catalogue').outerWidth() + 5 + 'px'}); } } // aside#archive的上下滑動(dòng) if($('aside#archive').outerHeight() < $(window).height()){ if($(document).scrollTop() <= $archiveOffestTop){ $('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); }else{ $('aside#archive').css({'position':'fixed','top':'0','left':$archiveOffestLeft + 'px'}); } }else if($('aside#archive').height() >= $(window).height() && $('aside#archive').outerHeight() < ($('footer').offset().top - $archiveOffestTop)){ if(($(document).scrollTop() + $(window).height()) <= ($('aside#archive').outerHeight() + $archiveOffestTop)){ $('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); }else if(($(document).scrollTop() + $(window).height()) < $('footer').offset().top){ $catalogue_top = $(window).height() - $('aside#archive').outerHeight(); $('aside#archive').css({'position':'fixed','top': $catalogue_top + 'px','left':$archiveOffestLeft + 'px'}); }else{ $catalogue_top = $(window).height() - $('aside#archive').outerHeight() - ($(document).height() - $('footer').offset().top); $('aside#archive').css({'position':'fixed','top':$catalogue_top + 'px','left':$archiveOffestLeft + 'px'}); } } }else{ // 如果屏幕不處于左側(cè),就讓這兩個(gè)跟隨歸位 $('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop}); $('#main').css({'padding-left':'0'}); $('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'}); } }).scroll().resize();
網(wǎng)絡(luò)上有很多相關(guān)的代碼,更有7行代碼解決此問(wèn)題的方法,甚至還有通用性的插件來(lái)實(shí)現(xiàn)此效果。然而它們都太過(guò)普遍化,對(duì)于不同的網(wǎng)站,特殊性不同,在一些細(xì)節(jié)上要做更多的考慮。
二、選擇用什么方式跟隨屏幕滾動(dòng)
方案有三種:
1、使用position:absolute;然后對(duì)top值進(jìn)行動(dòng)態(tài)賦值;
2、使用position:fixed;然后對(duì)top值進(jìn)行動(dòng)態(tài)賦值;
3、對(duì)padding-top或margin-top進(jìn)行動(dòng)態(tài)賦值;
前兩種都是用到了postion對(duì)元素的位置進(jìn)行安排,和float一樣,position將元素從正常的文本流中拖出來(lái)。而padding或margin的方法則是控制元素的邊距來(lái)實(shí)現(xiàn)。到底哪一種好呢?
使用position:absolute;會(huì)出現(xiàn)滾動(dòng)時(shí)發(fā)生抖動(dòng)(火狐中不會(huì)) ,使用padding-top時(shí)會(huì)讓有背景的元素看上去難看,也會(huì)發(fā)生抖動(dòng),使用position:fixed不支持IE6,使用margin-top沒(méi)有嘗試過(guò),應(yīng)該會(huì)發(fā)生抖動(dòng)。本段代碼選擇的是position:fixed,唯一不發(fā)生抖動(dòng)的方案,但是在IE6下不會(huì)有該效果。
三、要考慮的情況
之所以烏徒幫要將本站的代碼拿出來(lái)講解,是因?yàn)榫W(wǎng)上的代碼沒(méi)有具體分析,很多問(wèn)題都沒(méi)有考慮到。
1、要跟隨的元素的高度和屏幕的高度進(jìn)行比較
網(wǎng)上所有的代碼考慮的是該區(qū)域的高度小于窗口高度的情況,因此代碼很簡(jiǎn)單。當(dāng)區(qū)域高度等于和大于窗口高度時(shí),我們又會(huì)有新的考慮。
2、如果區(qū)域高度超出窗口,何時(shí)開(kāi)始跟隨滾動(dòng)?
這要看我們想給用戶展示什么,如果是一個(gè)廣告,如果是一段文字,如果是一個(gè)列表。我的設(shè)計(jì)是,當(dāng)屏幕往下滾動(dòng),但是還沒(méi)有將要顯示的元素全部顯示完整時(shí),不進(jìn)行任何效果,當(dāng)屏幕滾動(dòng)到元素的底部臨界處時(shí),效果觸發(fā),再往下滾動(dòng)時(shí),元素的底端和屏幕的底端對(duì)齊,元素的下部一直呈現(xiàn)在屏幕內(nèi)。當(dāng)然,不同的網(wǎng)頁(yè),你的設(shè)計(jì)自然不同,你也可能設(shè)計(jì)為,向下滾動(dòng)時(shí)先沒(méi)有效果,當(dāng)滾動(dòng)到某一個(gè)廣告之后,這個(gè)廣告和屏幕頂端對(duì)齊跟隨滾動(dòng)。
圖一 跟隨屏幕滾動(dòng)邏輯設(shè)計(jì)圖
從圖一中我們來(lái)看一下這一設(shè)計(jì)思路。圖中綠色部分為要跟隨滾動(dòng)的區(qū)域,灰色部分為整個(gè)網(wǎng)頁(yè),淺灰色部分為屏幕(能看到的區(qū)域)我們通過(guò)向下移動(dòng)淺灰色的屏幕來(lái)模擬往下滾動(dòng)滾動(dòng)條。在①的階段為初始階段,這個(gè)時(shí)候網(wǎng)頁(yè)一切照初始運(yùn)作,沒(méi)有任何動(dòng)作。到②的階段,屏幕向下滾動(dòng)到一個(gè)臨界點(diǎn),即要跟隨滾動(dòng)區(qū)域的最低端。第③階段是滾動(dòng)過(guò)臨界點(diǎn)之后,元素開(kāi)始跟隨屏幕滾動(dòng),我們可以看到,元素的底端和屏幕的底端對(duì)齊,元素的頂端已經(jīng)看不到。第④個(gè)階段的屏幕滾動(dòng)到底部,可以想象,網(wǎng)頁(yè)的底部是存在一些版權(quán)信息的,元素不能跟隨滾到底部把這些信息遮住,因此在紅線的地方就不再跟隨滾動(dòng)。
這是屏幕向下滾動(dòng)的示意圖,當(dāng)屏幕向上滾動(dòng)時(shí),這是這個(gè)順序的逆向。但是還有另外一個(gè)考慮,當(dāng)屏幕在向上滾動(dòng)時(shí)實(shí)現(xiàn)和向下滾動(dòng)初始狀的一種效果,即臨界點(diǎn)是此時(shí)④中的綠色區(qū)域頂端,向上滾動(dòng)時(shí)屏幕頂端和元素頂端對(duì)齊。出于技術(shù)難度的考慮,烏徒幫沒(méi)有實(shí)現(xiàn)這一效果。
3、數(shù)和量的計(jì)算
在滾動(dòng)時(shí),我們要掌握好那些量是變化的,哪些又不變,在不變中找變,在變中找不變,總之要保持頭腦清晰,分清如何去計(jì)算各種高度關(guān)系。
在圖一中,我用了一條藍(lán)色豎線來(lái)輔助高度計(jì)算,用紅色的線指示屏幕和元素的位置,將藍(lán)色豎線分成了a、b、c、d、e、f六段。那么他們之間有著哪些變化數(shù)量關(guān)系呢?(我們將綠色區(qū)域的元素定義為#myDiv,將版權(quán)信息在內(nèi)的底部定義為#footer)
a+b+c+d+e+f=$(document).height();//文檔高度,固定值 a= $('#myDiv').offset().top;//#myDiv頂部到文檔頂部的初始值,隨著滾動(dòng),$('#myDiv').offset().top將會(huì)變化 b=$('#myDiv').height();//元素的高度,固定值 a+b+c=$(window).scrollTop()=$(docment).scrollTop();//滾動(dòng)條的位置,即文檔頂端到當(dāng)前屏幕頂端的距離,不斷變化中 d=$(window).height();//屏幕的高度,固定值 f=$('#footer').height();//#footer的高度,固定值 a+b+c+d+e=$('#footer').offset().top=$(document).height()-$('#footer').height();//#footer頂部到文檔頂部的距離,固定值,不過(guò)需要注意的是,$('#footer').offset().top+$('#footer').height()并非一定等于$(document).height(),你要看#footer下面是否已經(jīng)沒(méi)有了空白。
在整個(gè)變化過(guò)程中,變化的值只有$(window).scrollTop()=$(docment).scrollTop()和$('#myDiv').offset().top,因此我們要抓住這些值之間的加減數(shù)量關(guān)系,做好邏輯判斷和賦值。
4、值在什么時(shí)候獲取
你可以看到,我在scroll事件之前事先獲取了
var $catalogueOffsetTop = $('aside#catalogue').offset().top; var $archiveOffestTop = $('aside#archive').offset().top; var $archiveOffestLeft = $('aside#archive').offset().left;
正是由于他們?cè)趕croll事件發(fā)生時(shí)會(huì)發(fā)生變化,因此要提前存放在變量中。
四、特殊情況特殊考慮
在寫出這么多代碼之前,我曾想過(guò)寫出一個(gè)可以通用的代碼,然而事情并非那么簡(jiǎn)單,在烏徒幫中,三個(gè)要滾動(dòng) 的區(qū)域都具有特殊性,因此必須認(rèn)真考慮他們的事件邏輯和仔細(xì)賦值。
1、元素是否自由隨意
由于烏徒幫雙擊屏幕滑向右側(cè)時(shí)出現(xiàn)的區(qū)域是自由的,頂部和底部沒(méi)有阻擋信息,因此我們的處理更方便一些,不用獲取頂部距離的初始值和考慮滾到底部時(shí)空出一段。但是仍然要考慮下面第2點(diǎn),屏幕和元素高度的比較。
而對(duì)于邊側(cè)欄的滾到,我們要考慮邊側(cè)欄頂部到文檔頂部還有一段距離,底部還有版權(quán)信息。滾到的位置要通過(guò)上文獲得的值,再配合css中獲得的值進(jìn)行精確計(jì)算。
2、判斷元素的高度和屏幕高度之間的關(guān)系
當(dāng)元素高度小的時(shí)候,我們的處理比較簡(jiǎn)單,只需要將元素頂端和屏幕頂端對(duì)齊,和上面第1點(diǎn)結(jié)合,也會(huì)出現(xiàn)不同的情況:如果元素頂部到文檔頂部還有一段距離的話,我們還不能屏幕一滾動(dòng)就開(kāi)始讓它和屏幕頂端對(duì)齊,而必須滾到它的頂端這個(gè)臨界點(diǎn)的時(shí)候才可以開(kāi)始。
而當(dāng)元素的高度大于屏幕的高度的時(shí)候,我們要進(jìn)行更復(fù)雜的判斷,和第1點(diǎn)判斷何時(shí)開(kāi)始跟隨滾動(dòng):只有當(dāng)屏幕的底端和元素底端對(duì)齊時(shí),元素開(kāi)始跟隨屏幕滾動(dòng)。
但是還有一種情況,即元素的高度超出了我們想要的高度,我們可以使用overflow來(lái)對(duì)元素進(jìn)行處理,這時(shí)我們通過(guò)元素的高度和頁(yè)面中一些固定值的比較來(lái)處理這一環(huán)節(jié)。烏徒幫通過(guò)比較右側(cè)元素的高度和底部的關(guān)系來(lái)進(jìn)行overflow的處理:
...... }else if($('#right-area').height() >= ($('footer').offset().top + $('footer').height())){ $('#right-area').height($('footer').offset().top + $('footer').height()).stop(true,true).css({'overflow':'hidden','overflow-y':'scroll'}); }
3、自己網(wǎng)頁(yè)內(nèi)特殊情況的變化
烏徒幫由于左右還可以滾動(dòng),因此產(chǎn)生了一系列問(wèn)題,position:fixed時(shí)左右方向上元素的距離并沒(méi)有固定值,因此在進(jìn)行左右滾動(dòng)時(shí),元素會(huì)遮住滾動(dòng)完的屏幕,因此我又對(duì)$(document).scrollLeft()進(jìn)行了判斷,進(jìn)行了一些處理。
另外,烏徒幫還是一個(gè)自適應(yīng)的網(wǎng)頁(yè)設(shè)計(jì)網(wǎng)站,在不同寬度的屏幕上顯示的效果也不同,js的特點(diǎn)是當(dāng)屏幕發(fā)生變化時(shí)仍然起作用,因此,我也增加了屏幕寬度的判斷。
總結(jié)
在跟隨屏幕滾動(dòng)這個(gè)問(wèn)題上,原始的思路是很簡(jiǎn)單的,即通過(guò)本文列舉的三種方案進(jìn)行位置或距離的動(dòng)態(tài)改變,然而,要在具體細(xì)節(jié)上把握好,必須對(duì)動(dòng)態(tài)變化中的各個(gè)數(shù)值有所把握。于此同時(shí),結(jié)合自己的網(wǎng)頁(yè),對(duì)不同情況下的動(dòng)態(tài)效果有一個(gè)好的設(shè)計(jì)和規(guī)劃,也是實(shí)現(xiàn)跟隨屏幕滾動(dòng)的關(guān)鍵環(huán)節(jié)。
以上這篇jquery跟隨屏幕滾動(dòng)效果的實(shí)現(xiàn)代碼就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
jQuery md5加密插件jQuery.md5.js用法示例
這篇文章主要介紹了jQuery md5加密插件jQuery.md5.js用法,結(jié)合實(shí)例形式簡(jiǎn)單分析了jQuery md5加密插件jquery.md5.js的簡(jiǎn)單使用技巧,需要的朋友可以參考下2018-08-08jQuery實(shí)現(xiàn)百葉窗焦點(diǎn)圖動(dòng)畫效果代碼分享(附源碼下載)
這篇文章主要介紹了jQuery實(shí)現(xiàn)百葉窗焦點(diǎn)圖動(dòng)畫效果代碼分享(附源碼下載)的相關(guān)資料,需要的朋友可以參考下2016-03-03淺析jquery數(shù)組刪除指定元素的方法:grep()
下面小編就為大家?guī)?lái)一篇淺析jquery數(shù)組刪除指定元素的方法:grep()。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05jquery改變disabled的boolean狀態(tài)的三種方法
改變disabled的boolean狀態(tài),下面為大家介紹三種比較不錯(cuò)的方法,大家可以參考下2013-12-12jquery用get實(shí)現(xiàn)ajax在ie里面刷新不進(jìn)入后臺(tái)解決方法
jquery用get實(shí)現(xiàn)ajax在ie里面刷新不進(jìn)入后臺(tái)的情況想必大家都有遇到過(guò)吧,下面與大家分享下具體的解決方法,希望對(duì)大家解決問(wèn)題有所幫助2013-08-08jquery動(dòng)態(tài)切換背景圖片的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了jquery動(dòng)態(tài)切換背景圖片的簡(jiǎn)單實(shí)現(xiàn)方法,涉及jQuery自定義函數(shù)結(jié)合時(shí)間函數(shù)動(dòng)態(tài)變換背景圖片的相關(guān)技巧,需要的朋友可以參考下2016-05-05jquery實(shí)現(xiàn)超簡(jiǎn)潔的TAB選項(xiàng)卡效果代碼
這篇文章主要介紹了jquery實(shí)現(xiàn)超簡(jiǎn)潔的TAB選項(xiàng)卡效果代碼,涉及jquery通過(guò)鼠標(biāo)click事件結(jié)合鏈?zhǔn)讲僮鲃?dòng)態(tài)操作tab選項(xiàng)卡的功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08