1. 程式人生 > 實用技巧 >JS DataURL 整理(二) DataURL 和圖片

JS DataURL 整理(二) DataURL 和圖片

一、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形式的圖片不會被瀏覽器快取,這意味著每次訪問這樣頁面時都被下載一次。這是一個使用效率方面的問題——尤其當這個圖片被整個網站大量使用的時候。

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;
});

更多:

JS DataURL 整理(一)

JavaScript 與 ECMAScript 的關係

新版本chrome瀏覽器(80版本以後)帶來的跨域請求cookie丟失問題