JS實現圖片預載入無需等待

来源:http://www.cnblogs.com/good10000/archive/2016/10/26/6000954.html
-Advertisement-
Play Games

網站開發時經常需要在某個頁面需要實現對大量圖片的瀏覽,如果考慮流量的話,大可以像pconline一樣每個頁面只顯示一張圖片,讓用戶每看一張圖片就需要重新下載一下整個頁面。不過,在web2.0時代,更多人願意用javascript來實現一個圖片瀏覽器,讓用戶無需等待過長的時間就能看到其他圖片。 知道了 ...


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

知道了一張圖片的地址,需要把它在一個固定大小的html容器(可以是div等)裡邊顯示出來,最重要的當然是需要知道這張即將顯示的圖片的寬和高,然後再結合容器的寬和高,按照一定的縮放比例使圖片顯示出來。因此,實現圖片預載入就成為圖片瀏覽器的核心功能了。 

做過圖片翻轉效果的朋友其實都知道,要讓圖片輪換的時候不出現等待,最好是先讓圖片下載到本地,讓瀏覽器緩存起來。這時,一般都會用到js裡邊的Image對象。一般的手段無非這樣: 

複製代碼代碼如下:
function preLoadImg(url) { 
var img = new Image(); 
img.src = url; 


通過調用preLoadImg函數,傳入圖片的url,就能使圖片預先下載下來了。實際上,這裡用到的預下載功能也和這基本一致。圖片預下載下來後,通過 img的width和height屬性,就能知道圖片的寬和高了。但是需要考慮到,在做圖片瀏覽器功能時,圖片都是實時顯示的。比如你點了顯示的按鈕,這個時候才會調用上邊類似的代碼來載入圖片。因此,如果你直接用img.width的時候,圖片還沒有完全下載下來。因此,需要用一些非同步的方法,等到圖片下載完畢的時候才會再對img的width和height進行調用。 

實現這樣的非同步方法實際上不難,圖片的下載完畢事件也很簡單,就是簡單的onload事件。因此,我們可以寫出下麵的代碼: 

複製代碼代碼如下:
function loadImage(url, callback) { 
var img = new Image(); 
img.src = url; 
img.onload = function(){ //圖片下載完畢時非同步調用callback函數。 
callback.call(img); // 將callback函數this指針切換為img。 
}; 


好了,再來寫一個測試用例。 

複製代碼代碼如下:
function imgLoaded(){ 
alert(this.width); 

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


在firefox中測試一下,發現不錯,果然和預想的效果一樣,在圖片下載後,就會彈出圖片的寬度來。無論點擊多少次或者刷新結果都一樣。 

不過,做到這一步,先別高興太早——還需要考慮一下瀏覽器的相容性,於是,趕緊到ie裡邊測試一下。沒錯,同樣彈出了圖片的寬度。但是,再點擊load的時候,情況就不一樣了,什麼反應都沒有了。刷新一下,也同樣如此。 

經過對多個瀏覽器版本的測試,發現ie6、opera都會這樣,而firefox和safari則表現正常。其實,原因也挺簡單的,就是因為瀏覽器的緩存了。當圖片載入過一次以後,如果再有對該圖片的請求時,由於瀏覽器已經緩存住這張圖片了,不會再發起一次新的請求,而是直接從緩存中載入過來。對於 firefox和safari,它們視圖使這兩種載入方式對用戶透明,同樣會引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會引起圖片的onload事件,因此上邊的代碼在它們裡邊不能得以實現效果。 

怎麼辦呢?最好的情況是Image可以有一個狀態值表明它是否已經載入成功了。從緩存載入的時候,因為不需要等待,這個狀態值就直接是表明已經下載了,而從http請求載入時,因為需要等待下載,這個值顯示為未完成。這樣的話,就可以搞定了。 

經過一些分析,終於發現一個為各個瀏覽器所相容的Image的屬性——complete。所以,在圖片onload事件之前先對這個值做一下判斷即可。最後,html代碼變成如下的樣子: 

複製代碼代碼如下:
function loadImage(url, callback) { 
var img = new Image(); //創建一個Image對象,實現圖片的預下載 
img.src = url; 
if (img.complete) { // 如果圖片已經存在於瀏覽器緩存,直接調用回調函數 
callback.call(img); 
return; // 直接返回,不用再處理onload事件 
} 
img.onload = function () { //圖片下載完畢時非同步調用callback函數。 
callback.call(img);//將回調函數的this替換為Image對象 
}; 
}; 

  


經過這麼一番折騰,總算是讓各個瀏覽器都能滿足我們的目標了。雖然代碼很簡單,但是卻把圖片瀏覽器中最核心的問題解決掉了,接下來你所要做的,僅僅是圖片如何呈現的問題了接下來看看另外一種方法:

複製代碼代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
<title>js 實現圖片預載入 載入完後執行動作</title> 
</head> 
<style type="text/css"> 
<!-- 
*html{ 
margin:0; 
padding:0; 
border:0; 
} 
body{border:1px solid #f3f3f3; background:#fefefe} 
div#loading{ 
width:950px; 
height:265px; 
line-height:265px; 
overflow:hidden; 
position:relative; 
text-align:center; 
} 
div#loading p{ 
position:static; 
+position:absolute; 
top:50%; 
vertical-align:middle; 
} 
div#loading p img{ 
position:static; 
+position:relative; 
top:-50%;left:-50%; 
vertical-align:middle 
} 
--> 
</style> 
<div id="loading"> 
<p><img src="http://www.baidu.com/img/baidu_logo.gif" /></p> 
</div> 
<script> 
var i=0; 
var c=3; 
var imgarr=new Array 
imgarr[0]="http://www.baidu.com/img/baidu_logo.gif"; 
imgarr[1]="http://img.baidu.com/img/logo-img.gif"; 
imgarr[2]="http://img.baidu.com/img/logo-zhidao.gif"; 
var Browser=new Object(); 
Browser.userAgent=window.navigator.userAgent.toLowerCase(); 
Browser.ie=/msie/.test(Browser.userAgent); 
Browser.Moz=/gecko/.test(Browser.userAgent); 
function SImage(url,callback) 
{ 
var img = new Image(); 
if(Browser.ie){ 
img.onreadystatechange =function(){ 
if(img.readyState=="complete"||img.readyState=="loaded"){ 
ii=i+1; 
callback(i); 
} 
} 
}else if(Browser.Moz){ 
img.onload=function(){ 
if(img.complete==true){ 
ii=i+1; 
callback(i); 
} 
} 
} 
img.src=url; 
} 
function icall(v) 
{ 
if(v<c){ 
SImage(""+imgarr[v]+"",icall); 
} 
else if(v>=c){ 
i=0; 
//location.replace('banner.html');//這裡寫自己的動作吧, 
} 
} 

  


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

-Advertisement-
Play Games
更多相關文章
  • 在實際開發中,經常會遇到導入Excel文件的需求,有的產品人想法更多,想要在前端直接判斷文件內容格式是否正確,必填項是否已填寫 依據HTML5的FileReader,可以使用新的API打開本地文件(參考這篇文章) FileReader.readAsBinaryString(Blob|File) Fi ...
  • 通讀官方教程 (guide) 的基礎篇。不要用任何構建工具,就只用最簡單的腳本引入,把教程里的例子模仿一遍,理解用法。不推薦上來就直接用 vue-cli 構建項目,尤其是如果沒有 Node/Webpack 基礎。有了 Node 和 Webpack 的基礎,可以通過 vue-cli 來搭建基於 Web... ...
  • 之前一直聽朋友談起gulp,但沒有使用過,最近有機會接觸到,現在給大家分享下,不對的地方還請指正。我一直以為互相分享是學習的一種好方式。下麵進入正題: 首先來瞭解下gulp,最起碼要知道:我們為什麼要學它,它的優勢。gulp是前端開發過程中對代碼進行構建的工具,它不僅能對網站資源進行優化,在開發過程 ...
  • 關於Sass的基本用法 百度搜索一大推 本人是從阮一峰大神的筆記開始接觸這個玩意 傳送門 http://www.ruanyifeng.com/blog/2012/06/sass.html 來了攜程之後從代替之前做樣式的女孩子從寫css開始乾起 明天女孩度產假歸來 可以擁入js的懷抱 一片新的天地 工 ...
  • 開發項目中用到了artDialog.js,從而專門學習一下如何配置和使用。 一、artDialog是什麼 artDialog是一個精巧的web對話框組件,壓縮後只有十多KB,並且不依賴其他框架。 二、artDialog的使用 以下內容引用 http://www.2cto.com/kf/201303/ ...
  • 最近做一個項目,需要javascript動態插入樣式,結果以前的方法失效了!查了2個小時的原因竟然是自己手賤,這個最後再說! javascript插入樣式在前端開發中應用比較廣泛,特別是在修改前端表現和頁面換膚的時候。最近做的這個任務是用戶在別人的站點上點擊一個按鈕,就會在別的站點頁面下插入一個腳本 ...
  • 例如: JSON字元串:var str1 = '{ "name": "cxh", "sex": "man" }'; JSON對象:var str2 = { "name": "cxh", "sex": "man" }; 一、JSON字元串轉換為JSON對象 要使用上面的str1,必須使用下麵的方法先轉 ...
  • 1.超鏈接<a href="http://www.100sucai.com/" title="100素材網">Welcome</a> 等效於js代碼 window.location.href="http://www.100sucai.com/"; //在同當前視窗中打開視窗 2.超鏈接<a href ...
一周排行
    -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# ...