jquery跟隨屏幕滾動代碼

来源:http://www.cnblogs.com/shouce/archive/2016/04/13/5385691.html
-Advertisement-
Play Games

我們在很多網站看到,當我們滾動網頁時,網頁內的廣告或某個小區域並不會消失,而是浮動在屏幕的某個地方,特別是一些局域廣告。那麼這是怎麼實現的呢?本文將引用烏徒幫的跟隨屏幕滾動代碼,對此效果做詳解。 一、原始代碼 下麵是烏徒幫的跟隨屏幕滾動代碼,它的作用域為烏徒幫網頁兩側的邊欄,以及雙擊屏幕後的右側隱藏 ...


我們在很多網站看到,當我們滾動網頁時,網頁內的廣告或某個小區域並不會消失,而是浮動在屏幕的某個地方,特別是一些局域廣告。那麼這是怎麼實現的呢?本文將引用烏徒幫的跟隨屏幕滾動代碼,對此效果做詳解。

一、原始代碼

下麵是烏徒幫的跟隨屏幕滾動代碼,它的作用域為烏徒幫網頁兩側的邊欄,以及雙擊屏幕後的右側隱藏欄。

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的跟隨屏幕滾動效果
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()){
// 這段範圍內是最關鍵的,允許滑動
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){ // 只有在屏幕處於左側的時候才進行下麵的跟隨滾動,同時需要註意下麵的if($(window).width() > 1024),是為了防止在小屏幕下還發生這種變化
// aside#catalogue的上下滑動
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的上下滑動
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{ // 如果屏幕不處於左側,就讓這兩個跟隨歸位
$('aside#catalogue').css({'position':'static','top':$catalogueOffsetTop});
$('#main').css({'padding-left':'0'});
$('aside#archive').css({'position':'static','top':$archiveOffestTop,'left':$archiveOffestLeft + 'px'});
}
}).scroll().resize();

網路上有很多相關的代碼,更有7行代碼解決此問題的方法,甚至還有通用性的插件來實現此效果。然而它們都太過普遍化,對於不同的網站,特殊性不同,在一些細節上要做更多的考慮。

二、選擇用什麼方式跟隨屏幕滾動

方案有三種:

1、使用position:absolute;然後對top值進行動態賦值;
2、使用position:fixed;然後對top值進行動態賦值;
3、對padding-top或margin-top進行動態賦值;

前兩種都是用到了postion對元素的位置進行安排,和float一樣,position將元素從正常的文本流中拖出來。而padding或margin的方法則是控制元素的邊距來實現。到底哪一種好呢?

使用position:absolute;會出現滾動時發生抖動(火狐中不會) ,使用padding-top時會讓有背景的元素看上去難看,也會發生抖動,使用position:fixed不支持IE6,使用margin-top沒有嘗試過,應該會發生抖動。本段代碼選擇的是position:fixed,唯一不發生抖動的方案,但是在IE6下不會有該效果。

三、要考慮的情況

之所以烏徒幫要將本站的代碼拿出來講解,是因為網上的代碼沒有具體分析,很多問題都沒有考慮到。

1、要跟隨的元素的高度和屏幕的高度進行比較

網上所有的代碼考慮的是該區域的高度小於視窗高度的情況,因此代碼很簡單。當區域高度等於和大於視窗高度時,我們又會有新的考慮。

2、如果區域高度超出視窗,何時開始跟隨滾動?

這要看我們想給用戶展示什麼,如果是一個廣告,如果是一段文字,如果是一個列表。我的設計是,當屏幕往下滾動,但是還沒有將要顯示的元素全部顯示完整時,不進行任何效果,當屏幕滾動到元素的底部臨界處時,效果觸發,再往下滾動時,元素的底端和屏幕的底端對齊,元素的下部一直呈現在屏幕內。當然,不同的網頁,你的設計自然不同,你也可能設計為,向下滾動時先沒有效果,當滾動到某一個廣告之後,這個廣告和屏幕頂端對齊跟隨滾動。

圖一 跟隨屏幕滾動邏輯設計圖

從圖一中我們來看一下這一設計思路。圖中綠色部分為要跟隨滾動的區域,灰色部分為整個網頁,淺灰色部分為屏幕(能看到的區域)我們通過向下移動淺灰色的屏幕來模擬往下滾動滾動條。在①的階段為初始階段,這個時候網頁一切照初始運作,沒有任何動作。到②的階段,屏幕向下滾動到一個臨界點,即要跟隨滾動區域的最低端。第③階段是滾動過臨界點之後,元素開始跟隨屏幕滾動,我們可以看到,元素的底端和屏幕的底端對齊,元素的頂端已經看不到。第④個階段的屏幕滾動到底部,可以想象,網頁的底部是存在一些版權信息的,元素不能跟隨滾到底部把這些信息遮住,因此在紅線的地方就不再跟隨滾動。

這是屏幕向下滾動的示意圖,當屏幕向上滾動時,這是這個順序的逆向。但是還有另外一個考慮,當屏幕在向上滾動時實現和向下滾動初始狀的一種效果,即臨界點是此時④中的綠色區域頂端,向上滾動時屏幕頂端和元素頂端對齊。出於技術難度的考慮,烏徒幫沒有實現這一效果。

3、數和量的計算

在滾動時,我們要掌握好那些量是變化的,哪些又不變,在不變中找變,在變中找不變,總之要保持頭腦清晰,分清如何去計算各種高度關係。

在圖一中,我用了一條藍色豎線來輔助高度計算,用紅色的線指示屏幕和元素的位置,將藍色豎線分成了a、b、c、d、e、f六段。那麼他們之間有著哪些變化數量關係呢?(我們將綠色區域的元素定義為#myDiv,將版權信息在內的底部定義為#footer)

a+b+c+d+e+f=$(document).height();//文檔高度,固定值

a= $('#myDiv').offset().top;//#myDiv頂部到文檔頂部的初始值,隨著滾動,$('#myDiv').offset().top將會變化

b=$('#myDiv').height();//元素的高度,固定值

a+b+c=$(window).scrollTop()=$(docment).scrollTop();//滾動條的位置,即文檔頂端到當前屏幕頂端的距離,不斷變化中

d=$(window).height();//屏幕的高度,固定值

f=$('#footer').height();//#footer的高度,固定值

a+b+c+d+e=$('#footer').offset().top=$(document).height()-$('#footer').height();//#footer頂部到文檔頂部的距離,固定值,不過需要註意的是,$('#footer').offset().top+$('#footer').height()並非一定等於$(document).height(),你要看#footer下麵是否已經沒有了空白。

在整個變化過程中,變化的值只有$(window).scrollTop()=$(docment).scrollTop()和$('#myDiv').offset().top,因此我們要抓住這些值之間的加減數量關係,做好邏輯判斷和賦值。

4、值在什麼時候獲取

你可以看到,我在scroll事件之前事先獲取了

var $catalogueOffsetTop = $('aside#catalogue').offset().top;
var $archiveOffestTop = $('aside#archive').offset().top;
var $archiveOffestLeft = $('aside#archive').offset().left;

正是由於他們在scroll事件發生時會發生變化,因此要提前存放在變數中。

四、特殊情況特殊考慮

在寫出這麼多代碼之前,我曾想過寫出一個可以通用的代碼,然而事情並非那麼簡單,在烏徒幫中,三個要滾動 的區域都具有特殊性,因此必須認真考慮他們的事件邏輯和仔細賦值。

1、元素是否自由隨意

由於烏徒幫雙擊屏幕滑向右側時出現的區域是自由的,頂部和底部沒有阻擋信息,因此我們的處理更方便一些,不用獲取頂部距離的初始值和考慮滾到底部時空出一段。但是仍然要考慮下麵第2點,屏幕和元素高度的比較。

而對於邊側欄的滾到,我們要考慮邊側欄頂部到文檔頂部還有一段距離,底部還有版權信息。滾到的位置要通過上文獲得的值,再配合css中獲得的值進行精確計算。

2、判斷元素的高度和屏幕高度之間的關係

當元素高度小的時候,我們的處理比較簡單,只需要將元素頂端和屏幕頂端對齊,和上面第1點結合,也會出現不同的情況:如果元素頂部到文檔頂部還有一段距離的話,我們還不能屏幕一滾動就開始讓它和屏幕頂端對齊,而必須滾到它的頂端這個臨界點的時候才可以開始。

而當元素的高度大於屏幕的高度的時候,我們要進行更複雜的判斷,和第1點判斷何時開始跟隨滾動:只有當屏幕的底端和元素底端對齊時,元素開始跟隨屏幕滾動。

但是還有一種情況,即元素的高度超出了我們想要的高度,我們可以使用overflow來對元素進行處理,這時我們通過元素的高度和頁面中一些固定值的比較來處理這一環節。烏徒幫通過比較右側元素的高度和底部的關係來進行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、自己網頁內特殊情況的變化

烏徒幫由於左右還可以滾動,因此產生了一系列問題,position:fixed時左右方向上元素的距離並沒有固定值,因此在進行左右滾動時,元素會遮住滾動完的屏幕,因此我又對$(document).scrollLeft()進行了判斷,進行了一些處理。

另外,烏徒幫還是一個自適應的網頁設計網站,在不同寬度的屏幕上顯示的效果也不同,js的特點是當屏幕發生變化時仍然起作用,因此,我也增加了屏幕寬度的判斷。

總結

在跟隨屏幕滾動這個問題上,原始的思路是很簡單的,即通過本文列舉的三種方案進行位置或距離的動態改變,然而,要在具體細節上把握好,必須對動態變化中的各個數值有所把握。於此同時,結合自己的網頁,對不同情況下的動態效果有一個好的設計和規劃,也是實現跟隨屏幕滾動的關鍵環節。

原文:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關於rem實現屏幕自適應佈局的討論還是比較多的,剛好我也看到使用rem實現自適應的web app,所以也來湊下熱鬧。 說起rem,免不了要聯繫到em、px,這裡簡單提提他們的定義和特點。 1. px:像素(Pixel),相對長度單位。像素px是相對於顯示器屏幕解析度而言的,手機上的100px和電腦上 ...
  • HTML 格式化標簽 HTML 使用標簽<b> 與<i> 對輸出的文本進行格式, 如:粗體 or 斜體 這些HTML標簽被稱為格式化標簽 通常標簽 <strong> 替換加粗標簽 <b> 來使用, <em> 替換 <i>標簽使用。 然而,這些標簽的含義是不同的: <b> 與<i> 定義粗體或斜體文本 ...
  • 1.離線緩存為HTML5開發移動應用提供了基礎 HTML5 Web Storage API可以看做是加強版的cookie,不受數據大小限制,有更好的彈性以及架構,可以將數據寫入到本機的ROM中,還可以在關閉瀏覽器後再次打開時恢複數據,以減少網路流量。 同時,這個功能算得上是另一個方向的後臺“操作記錄 ...
  • 效果預覽:http://hovertree.com/texiao/css/22/代碼如下: 源碼下載:http://hovertree.com/h/bjaf/l243x19a.htm 轉自:http://hovertree.com/h/bjaf/2hhi6cjy.htm 更多特效:http://ww ...
  • ...
  • div內嵌套p,div等元素出現的問題 http://caiceclb.iteye.com/blog/428085 文章內有些問題,可能不適應今天了。 正在學習前端,小問題是不能忽視的。 解決方案1是有問題的,margin:-1px;並不能解決高度增大問題,chrome,FF,Opara測試了下都不 ...
  • 用語義化標簽去寫你的HTML,相容IE6,7,8 HTML5增加了更多語義化的標簽,如header,footer,nav……讓我們在頁面編寫的時候,不需要再用下麵這種方法去佈局了: ? <div class="header">這是頭部</div> <div class="content">這是中間內 ...
  • 隨著科技的不斷發展,需要改變營銷策略的一個企業就變得非常重要。你不能指望用你的營銷工具來留住你的客戶。智能手機和平板電腦已經改變了消費者的行為方式。現在,人們甚至不想去他們的電腦或筆記本電腦,以檢查產品或服務,他們的願望。用智能手機在他們的手中,他們擁有的所有信息,他們需要在他們的指尖。因此,它已成 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...