一、Data URL 和圖片
Data URL給了我們一種很巧妙的將圖片“嵌入”到HTML中的方法。跟傳統的用img
標記將服務器上的圖片引用到頁面中的方式不一樣,在Data URL協議中,圖片被轉換成base64編碼的字符串形式,並存儲在URL中,冠以mime-type。本文中,我將介紹如何巧妙的使用Data URL優化網站加載速度和執行效率。
1. Data URL基本原理
圖片在網頁中的使用方法通常是下面這種利用img
標記的形式:
<img src="images/myimage.gif ">
這種方式中,img
標記的src
屬性指定了一個遠程服務器上的資源。當網頁加載到瀏覽器中時,瀏覽器會針對每個外部資源都向服務器發送一次拉取資源請求,占用網絡資源。大多數的瀏覽器都有一個並發請求數不能超過4個的限制。這意味着,如果一個網頁里嵌入了過多的外部資源,這些請求會導致整個頁面的加載延遲。而使用Data URL技術,圖片數據以base64字符串格式嵌入到了頁面中,與HTML成為一體,它的形式如下:
<img src="data:image/gif;base64,R0lGODlhMwAxAIAAAAAAAP/// yH5BAAAAAAALAAAAAAzADEAAAK8jI+pBr0PowytzotTtbm/DTqQ6C3hGX ElcraA9jIr66ozVpM3nseUvYP1UEHF0FUUHkNJxhLZfEJNvol06tzwrgd LbXsFZYmSMPnHLB+zNJFbq15+SOf50+6rG7lKOjwV1ibGdhHYRVYVJ9Wn k2HWtLdIWMSH9lfyODZoZTb4xdnpxQSEF9oyOWIqp6gaI9pI1Qo7BijbF ZkoaAtEeiiLeKn72xM7vMZofJy8zJys2UxsCT3kO229LH1tXAAAOw==">
從上面的base64字符串中你看不出任何跟圖片相關的東西,但下面,我們將傳統的img
寫法和現在的Data URL用法左右對比顯示,你就能看出它們是完全一樣的效果。但實際上它們是不一樣的,它們一個是引用了外部資源,一個是使用了Data URL。
2.Data URL 的優勢和劣勢
優勢:
- 當訪問外部資源很麻煩或受限時
- 當圖片是在服務器端用程序動態生成,每個訪問用戶顯示的都不同時。
- 當圖片的體積太小,占用一個HTTP會話不是很值得時。
- 可以減少網絡請求。
- 字符串編碼方便傳輸存儲。
劣勢:
- Base64編碼的數據體積通常是原數據的體積4/3,也就是Data URL形式的圖片會比二進制格式的圖片體積大1/3。
- Data URL形式的圖片不會被瀏覽器緩存,這意味着每次訪問這樣頁面時都被下載一次。這是一個使用效率方面的問題——尤其當這個圖片被整個網站大量使用的時候。
- 不能在客戶端進行緩存。(如圖片,只能通過css文件進行背景圖片緩存)
- 渲染時需要base64解碼,需要消耗cpu資源。
3.Css 中使用Data URL
.striped_box { width: 100px; height: 100px; background-image: url("data:image/gif;base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7"); border: 1px solid gray; padding: 10px; }
二、JS里DataURL、File、Blob及canvas對象間互相轉換的方法函數
1》:canvas轉換為dataURL :
var canvas = document.createElement("canvas"); var imgsrc = canvas.toDataURL('image/jpeg',0.8);//第二個參數指圖片質量
2》:file/Blob對象轉換為dataURL:
file對象其實也是blob對象,所以兩者轉換為dataURL的方法一樣:
function readBlobAsDataURL(blob, callback) { var a = new FileReader(); a.onload = function(e) {callback(e.target.result);}; a.readAsDataURL(blob); } //example: readBlobAsDataURL(blob, function (dataurl){ console.log(dataurl); }); readBlobAsDataURL(file, function (dataurl){ console.log(dataurl); });
3》:dataURL轉換為Blob對象、dataURL轉換為File對象
function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime}); } function dataURLtoFile(dataurl, filename) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type:mime}); } //test: var blob = dataURLtoBlob('data:text/plain;base64,YWFhYWFhYQ=='); var file = dataURLtoFile('data:text/plain;base64,YWFhYWFhYQ==', 'test.txt');
4》:dataURL圖片數據繪制到canvas:
var img = new Image(); img.onload = function(){ canvas.drawImage(img); }; img.src = dataurl;
5》:File,Blob的圖片文件數據繪制到canvas:
readBlobAsDataURL(file, function (dataurl){ var img = new Image(); img.onload = function(){ canvas.drawImage(img); }; img.src = dataurl; });
更多: