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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...