paulwong

          My Links

          Blog Stats

          常用鏈接

          留言簿(67)

          隨筆分類(1393)

          隨筆檔案(1151)

          文章分類(7)

          文章檔案(10)

          相冊

          收藏夾(2)

          AI

          Develop

          E-BOOK

          Other

          養(yǎng)生

          微服務(wù)

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          60天內(nèi)閱讀排行

          javascript圖片瀏覽器的核心——圖片預(yù)加載

          網(wǎng)站開發(fā)時(shí)經(jīng)常需要在某個(gè)頁面需要實(shí)現(xiàn)對大量圖片的瀏覽,如果考慮流量的話,大可以像pconline一樣每個(gè)頁面只顯示一張圖片,讓用戶每看一張圖片就需要重新下載一下整個(gè)頁面。不過,在web2.0時(shí)代,更多人愿意用javascript來實(shí)現(xiàn)一個(gè)圖片瀏覽器,讓用戶無需等待過長的時(shí)間就能看到其他圖片。

          知道了一張圖片的地址,需要把它在一個(gè)固定大小的html容器(可以是div等)里邊顯示出來,最重要的當(dāng)然是需要知道這張即將顯示的圖片的寬和高,然后再結(jié)合容器的寬和高,按照一定的縮放比例使圖片顯示出來。因此,實(shí)現(xiàn)圖片預(yù)加載就成為圖片瀏覽器的核心功能了。

          做過圖片翻轉(zhuǎn)效果的朋友其實(shí)都知道,要讓圖片輪換的時(shí)候不出現(xiàn)等待,最好是先讓圖片下載到本地,讓瀏覽器緩存起來。這時(shí),一般都會用到j(luò)s里邊的Image對象。一般的手段無非這樣:

          function preLoadImg(url) {
          var img = new Image();
          img.src 
          = url;
          }


          通過調(diào)用preLoadImg函數(shù),傳入圖片的url,就能使圖片預(yù)先下載下來了。實(shí)際上,這里用到的預(yù)下載功能也和這基本一致。圖片預(yù)下載下來后,通過 img的width和height屬性,就能知道圖片的寬和高了。但是需要考慮到,在做圖片瀏覽器功能時(shí),圖片都是實(shí)時(shí)顯示的。比如你點(diǎn)了顯示的按鈕,這個(gè)時(shí)候才會調(diào)用上邊類似的代碼來加載圖片。因此,如果你直接用img.width的時(shí)候,圖片還沒有完全下載下來。因此,需要用一些異步的方法,等到圖片下載完畢的時(shí)候才會再對img的width和height進(jìn)行調(diào)用。 實(shí)現(xiàn)這樣的異步方法實(shí)際上不難,圖片的下載完畢事件也很簡單,就是簡單的onload事件。因此,我們可以寫出下面的代碼:


          function loadImage(url, callback) {
          var img = new Image();
          img.src 
          = url;

          img.onload 
          = function()//圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
          callback.call(img); // 將callback函數(shù)this指針切換為img。
          }
          ;
          }


          好了,再來寫一個(gè)測試用例。


          function imgLoaded(){
          alert(
          this.width);
          }


          <input type="button" value="loadImage" onclick="loadImage('aaa.jpg',imgLoaded)"/>

          在firefox中測試一下,發(fā)現(xiàn)不錯(cuò),果然和預(yù)想的效果一樣,在圖片下載后,就會彈出圖片的寬度來。無論點(diǎn)擊多少次或者刷新結(jié)果都一樣。

          不過,做到這一步,先別高興太早——還需要考慮一下瀏覽器的兼容性,于是,趕緊到ie里邊測試一下。沒錯(cuò),同樣彈出了圖片的寬度。但是,再點(diǎn)擊load的時(shí)候,情況就不一樣了,什么反應(yīng)都沒有了。刷新一下,也同樣如此。

          經(jīng)過對多個(gè)瀏覽器版本的測試,發(fā)現(xiàn)ie6、opera都會這樣,而firefox和safari則表現(xiàn)正常。其實(shí),原因也挺簡單的,就是因?yàn)闉g覽器的緩存了。當(dāng)圖片加載過一次以后,如果再有對該圖片的請求時(shí),由于瀏覽器已經(jīng)緩存住這張圖片了,不會再發(fā)起一次新的請求,而是直接從緩存中加載過來。對于 firefox和safari,它們視圖使這兩種加載方式對用戶透明,同樣會引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會引起圖片的onload事件,因此上邊的代碼在它們里邊不能得以實(shí)現(xiàn)效果。

          怎么辦呢?最好的情況是Image可以有一個(gè)狀態(tài)值表明它是否已經(jīng)載入成功了。從緩存加載的時(shí)候,因?yàn)椴恍枰却?,這個(gè)狀態(tài)值就直接是表明已經(jīng)下載了,而從http請求加載時(shí),因?yàn)樾枰却螺d,這個(gè)值顯示為未完成。這樣的話,就可以搞定了。

          經(jīng)過一些分析,終于發(fā)現(xiàn)一個(gè)為各個(gè)瀏覽器所兼容的Image的屬性——complete。所以,在圖片onload事件之前先對這個(gè)值做一下判斷即可。最后,代碼變成如下的樣子:


          function loadImage(url, callback) {
          var img = new Image(); //創(chuàng)建一個(gè)Image對象,實(shí)現(xiàn)圖片的預(yù)下載
          img.src = url;

          if (img.complete) // 如果圖片已經(jīng)存在于瀏覽器緩存,直接調(diào)用回調(diào)函數(shù)
          callback.call(img);
          return// 直接返回,不用再處理onload事件
          }


          img.onload 
          = function () //圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
          callback.call(img);//將回調(diào)函數(shù)的this替換為Image對象
          }
          ;
          }
          ;

          經(jīng)過這么一番折騰,總算是讓各個(gè)瀏覽器都能滿足我們的目標(biāo)了。雖然代碼很簡單,但是卻把圖片瀏覽器中最核心的問題解決掉了,接下來你所要做的,僅僅是圖片如何呈現(xiàn)的問題了。

          posted on 2010-11-13 17:24 paulwong 閱讀(492) 評論(0)  編輯  收藏 所屬分類: DHTML

          主站蜘蛛池模板: 库车县| 阿鲁科尔沁旗| 青川县| 泌阳县| 新河县| 大理市| 香河县| 永新县| 资源县| 新竹县| 绥滨县| 宁阳县| 田林县| 鄂州市| 女性| 伊金霍洛旗| 海丰县| 衡阳市| 舟山市| 永新县| 黑山县| 卓资县| 陕西省| 嵊泗县| 米林县| 连平县| 图木舒克市| 娱乐| 锦州市| 彰化市| 岱山县| 长沙市| 峨山| 海宁市| 渝北区| 麟游县| 峨边| 印江| 马公市| 花莲市| 买车|