利用canvas中toDataURL()將圖片轉為dataURL(base64)的方法詳解
將圖片轉為base64的好處
將圖片轉換為Base64編碼,可以讓你很方便地在沒有上傳文件的條件下將圖片插入其它的網頁、編輯器中。 這對于一些小的圖片是極為方便的,因為你不需要再去尋找一個保存圖片的地方。
將圖片轉換成base64編碼的,在web網上一般用于小圖片上,不僅可以減少圖片的請求數量(集合到js、css代碼中),還可以防止因為一些相對路徑等問題導致圖片404錯誤。
引言
假設一個應用場景:由于某些特殊原因從服務端請求到圖片路徑,要求通過該路徑獲取對應圖片的 base64 dataURL。在這個場景中,我們首先推斷該圖片路徑是可訪問的,同時還需要一種將圖片轉換到 dataURL 的方法。
我們如何實現它呢?
dataURL
先大致回顧下正統的 dataURL 的語法,這有助于我們檢驗轉換后的內容是否正確。一個完整的 dataURI 應該是這樣的:
data:[<mediatype>][;base64],<data>
其中mediatype聲明了文件類型,遵循MIME規(guī)則,如“image/png”、“text/plain”;之后是編碼類型,這里我們只涉及 base64;緊接著就是文件編碼后的內容了。我們常常在 HTML 里看到img標簽的src會這樣寫:
src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7"
這個img引用的就是以 base64 編碼的 dataURL 了,只要瀏覽器支持,就可以被解碼成 gif 圖片并渲染出來。
.toDataURL()
FileReader對象也有類似的方法,比如.readAsDataURL()
,然而它只接受file或blob類型,而這兩種類型一般只能通過<input[type=file]>
元素的files屬性獲取,或者用Blob()構造函數手工創(chuàng)建一個新的對象。尷尬的是我們當前只有圖片路徑,受制于瀏覽器的安全策略, <input[type=file]>
的files屬性是只讀的,而Blob()構造函數只接受文件內容,兩種方式都無法通過圖片路徑直接獲取。上文中假設的應用場景迫使我們必先考慮如何通過路徑獲取到圖片內容。<img>是可以的,并且可以被繪制到<canvas>中,而<canvas>正巧擁有.toDataURL()
方法。
萬事具備,我們只需要把<img>獲取到的圖片放到<canvas>里再通過.toDataURL()
方法轉化下,就可以得到以 base64 編碼的 dataURL。來看這個方法的語法:
canvas.toDataURL([type, encoderOptions]);
canvas是DOM元素<canvas>對象;參數type指定圖片類型,如果指定的類型不被支持則以默認值image/png替代;encoderOptions可以為image/jpeg或image/webp類型的圖片設置圖片質量,取值0-1,超出則以默認值0.92替代。
需要注意的是:在轉換成 dataURL 前必須先確保圖片成功加載到,于是.toDataURL()
方法應該寫在<img>的onload異步事件中?,F在就來實現一個功能函數:
function getBase64(url){ //通過構造函數來創(chuàng)建的 img 實例,在賦予 src 值后就會立刻下載圖片,相比 createElement() 創(chuàng)建 <img> 省去了 append(),也就避免了文檔冗余和污染 var Img = new Image(), dataURL=''; Img.src=url; Img.onload=function(){ //要先確保圖片完整獲取到,這是個異步事件 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'); //轉換圖片為dataURL }; }
一個可供隨時調用的轉換函數完成了,它會在圖片被加載后返回一整個 dataURL 字符串。
完善
onload事件確保了轉換任務在加載后執(zhí)行,卻又帶來了新問題——dataURL 只有在圖片加載完成后才會返回,我們無法確定圖片什么時候完成加載。如果后續(xù)要對 dataURL 做相關處理(比如傳遞到其他服務器)的話,添加一個回調是必要的,這能確保后續(xù)處理任務在成功得到 dataURL 之后執(zhí)行,我們需要修改getBase64()
:
function getBase64(url,callback){ //添加一個回調參數 ... Img.onload=function(){ ... canvas.getContext("2d").drawImage(Img,0,0,width,height); dataURL=canvas.toDataURL('image/jpeg'); callback?callback(dataURL):null; //調用回調函數 }; }
在執(zhí)行時添加回調:
getBase64('//upload.jianshu.io/users/upload_avatars/555630/fdd1b798e6b0.jpg',(dataURL)=>{ console.log(dataURL); });
就是這樣,如果不考慮兼容性的話,或許我們可以用 promise 和 generator 來實現,再添加一些錯誤處理就更完美了。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
JS中使用apply、bind實現為函數或者類傳入動態(tài)個數的參數
這篇文章主要介紹了JS中使用apply、bind實現為函數或者類傳入動態(tài)個數的參數的相關資料,需要的朋友可以參考下2016-04-04Chrome不支持showModalDialog模態(tài)對話框和無法返回returnValue問題的解決方法
上個禮拜修改測試一個后臺管理項目,在測試與各個瀏覽器兼容性的時候,發(fā)現在chrome瀏覽器下showModalDialog方法顯示的并不是模態(tài)對話框,就像新打開一個頁面一樣,父窗口仍然可以隨意獲取焦點,并可以打開多個窗體,而且返回值returnValue也無法返回,一直是undefined2016-10-10將HTMLCollection/NodeList/偽數組轉換成數組的實現方法
將HTMLCollection/NodeList/偽數組轉換成數組的實現方法,需要的朋友可以參考下。2011-06-06