利用canvas中toDataURL()將圖片轉(zhuǎn)為dataURL(base64)的方法詳解
將圖片轉(zhuǎn)為base64的好處
將圖片轉(zhuǎn)換為Base64編碼,可以讓你很方便地在沒有上傳文件的條件下將圖片插入其它的網(wǎng)頁、編輯器中。 這對(duì)于一些小的圖片是極為方便的,因?yàn)槟悴恍枰偃ふ乙粋€(gè)保存圖片的地方。
將圖片轉(zhuǎn)換成base64編碼的,在web網(wǎng)上一般用于小圖片上,不僅可以減少圖片的請(qǐng)求數(shù)量(集合到j(luò)s、css代碼中),還可以防止因?yàn)橐恍┫鄬?duì)路徑等問題導(dǎo)致圖片404錯(cuò)誤。
引言
假設(shè)一個(gè)應(yīng)用場景:由于某些特殊原因從服務(wù)端請(qǐng)求到圖片路徑,要求通過該路徑獲取對(duì)應(yīng)圖片的 base64 dataURL。在這個(gè)場景中,我們首先推斷該圖片路徑是可訪問的,同時(shí)還需要一種將圖片轉(zhuǎn)換到 dataURL 的方法。
我們?nèi)绾螌?shí)現(xiàn)它呢?
dataURL
先大致回顧下正統(tǒng)的 dataURL 的語法,這有助于我們檢驗(yàn)轉(zhuǎn)換后的內(nèi)容是否正確。一個(gè)完整的 dataURI 應(yīng)該是這樣的:
data:[<mediatype>][;base64],<data>
其中mediatype聲明了文件類型,遵循MIME規(guī)則,如“image/png”、“text/plain”;之后是編碼類型,這里我們只涉及 base64;緊接著就是文件編碼后的內(nèi)容了。我們常常在 HTML 里看到img標(biāo)簽的src會(huì)這樣寫:
src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7"
這個(gè)img引用的就是以 base64 編碼的 dataURL 了,只要瀏覽器支持,就可以被解碼成 gif 圖片并渲染出來。
.toDataURL()
FileReader對(duì)象也有類似的方法,比如.readAsDataURL() ,然而它只接受file或blob類型,而這兩種類型一般只能通過<input[type=file]>元素的files屬性獲取,或者用Blob()構(gòu)造函數(shù)手工創(chuàng)建一個(gè)新的對(duì)象。尷尬的是我們當(dāng)前只有圖片路徑,受制于瀏覽器的安全策略, <input[type=file]>的files屬性是只讀的,而Blob()構(gòu)造函數(shù)只接受文件內(nèi)容,兩種方式都無法通過圖片路徑直接獲取。上文中假設(shè)的應(yīng)用場景迫使我們必先考慮如何通過路徑獲取到圖片內(nèi)容。<img>是可以的,并且可以被繪制到<canvas>中,而<canvas>正巧擁有.toDataURL()方法。
萬事具備,我們只需要把<img>獲取到的圖片放到<canvas>里再通過.toDataURL()方法轉(zhuǎn)化下,就可以得到以 base64 編碼的 dataURL。來看這個(gè)方法的語法:
canvas.toDataURL([type, encoderOptions]);
canvas是DOM元素<canvas>對(duì)象;參數(shù)type指定圖片類型,如果指定的類型不被支持則以默認(rèn)值image/png替代;encoderOptions可以為image/jpeg或image/webp類型的圖片設(shè)置圖片質(zhì)量,取值0-1,超出則以默認(rèn)值0.92替代。
需要注意的是:在轉(zhuǎn)換成 dataURL 前必須先確保圖片成功加載到,于是.toDataURL()方法應(yīng)該寫在<img>的onload異步事件中?,F(xiàn)在就來實(shí)現(xiàn)一個(gè)功能函數(shù):
function getBase64(url){
//通過構(gòu)造函數(shù)來創(chuàng)建的 img 實(shí)例,在賦予 src 值后就會(huì)立刻下載圖片,相比 createElement() 創(chuàng)建 <img> 省去了 append(),也就避免了文檔冗余和污染
var Img = new Image(),
dataURL='';
Img.src=url;
Img.onload=function(){ //要先確保圖片完整獲取到,這是個(gè)異步事件
var canvas = document.createElement("canvas"), //創(chuàng)建canvas元素
width=Img.width, //確保canvas的尺寸和圖片一樣
height=Img.height;
canvas.width=width;
canvas.height=height;
canvas.getContext("2d").drawImage(Img,0,0,width,height); //將圖片繪制到canvas中
dataURL=canvas.toDataURL('image/jpeg'); //轉(zhuǎn)換圖片為dataURL
};
}
一個(gè)可供隨時(shí)調(diào)用的轉(zhuǎn)換函數(shù)完成了,它會(huì)在圖片被加載后返回一整個(gè) dataURL 字符串。
完善
onload事件確保了轉(zhuǎn)換任務(wù)在加載后執(zhí)行,卻又帶來了新問題——dataURL 只有在圖片加載完成后才會(huì)返回,我們無法確定圖片什么時(shí)候完成加載。如果后續(xù)要對(duì) dataURL 做相關(guān)處理(比如傳遞到其他服務(wù)器)的話,添加一個(gè)回調(diào)是必要的,這能確保后續(xù)處理任務(wù)在成功得到 dataURL 之后執(zhí)行,我們需要修改getBase64() :
function getBase64(url,callback){ //添加一個(gè)回調(diào)參數(shù)
...
Img.onload=function(){
...
canvas.getContext("2d").drawImage(Img,0,0,width,height);
dataURL=canvas.toDataURL('image/jpeg');
callback?callback(dataURL):null; //調(diào)用回調(diào)函數(shù)
};
}
在執(zhí)行時(shí)添加回調(diào):
getBase64('//upload.jianshu.io/users/upload_avatars/555630/fdd1b798e6b0.jpg',(dataURL)=>{
console.log(dataURL);
});
就是這樣,如果不考慮兼容性的話,或許我們可以用 promise 和 generator 來實(shí)現(xiàn),再添加一些錯(cuò)誤處理就更完美了。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
JS簡單實(shí)現(xiàn)無縫滾動(dòng)效果實(shí)例
這篇文章主要介紹了JS簡單實(shí)現(xiàn)無縫滾動(dòng)效果,結(jié)合完整實(shí)例形式分析了javascript實(shí)現(xiàn)圖片無縫滾動(dòng)效果的實(shí)現(xiàn)技巧,涉及javascript結(jié)合時(shí)間函數(shù)定時(shí)觸發(fā)動(dòng)態(tài)修改頁面元素屬性的相關(guān)操作方法,需要的朋友可以參考下2016-08-08
微信小程序時(shí)間標(biāo)簽和時(shí)間范圍的聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了微信小程序時(shí)間標(biāo)簽和時(shí)間范圍的聯(lián)動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
使用Cookies保存網(wǎng)站歷史瀏覽記錄實(shí)例代碼
仿淘寶網(wǎng)的最近瀏覽記錄功能,喜歡的朋友可以參考下。2010-07-07
js中的onchange和onpropertychange (onchange無效的解決方法)
這篇文章主要介紹了js中的onchange和onpropertychange (onchange無效的解決方法),需要的朋友可以過來參考下,希望對(duì)大家有所幫助2014-03-03
基于JavaScript實(shí)現(xiàn)文本一鍵復(fù)制和長按復(fù)制功能
本文主要內(nèi)容分三部分,第一部分是需求分析,第二部分是實(shí)現(xiàn)步驟,第三部分是問題詳解,如果您只需要解決問題,請(qǐng)閱讀第一、二部分即可,如果您有更多時(shí)間,進(jìn)一步學(xué)習(xí)問題相關(guān)知識(shí)點(diǎn),請(qǐng)閱讀至第三部分2023-10-10
HTML頁面滾動(dòng)時(shí)獲取離頁面頂部的距離2種實(shí)現(xiàn)方法
獲取離滾動(dòng)頁面的頂部距離有兩種方法一是DOM;而是jquery,具體的實(shí)現(xiàn)如下,感興趣的朋友可以嘗試操作下2013-09-09
微信小程序?qū)崿F(xiàn)購物頁面左右聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)購物頁面左右聯(lián)動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
HTML頁面,測試JS對(duì)C函數(shù)的調(diào)用簡單實(shí)例
下面小編就為大家?guī)硪黄狧TML頁面,測試JS對(duì)C函數(shù)的調(diào)用簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08

