canvas-toDataURL()將圖片轉為dataURL(base64)

來源:互聯網
上載者:User
將圖片轉為base64的好處

將圖片轉換為Base64編碼,可以讓你很方便地在沒有上傳檔案的條件下將圖片插入其它的網頁、編輯器中。 這對於一些小的圖片是極為方便的,因為你不需要再去尋找一個儲存圖片的地方。

將圖片轉換成base64編碼的,在web網上一般用於小圖片上,不僅可以減少圖片的請求數量(集合到js、css代碼中),還可以防止因為一些相對路徑等問題導致圖片404錯誤。

一個應用情境:由於某些特殊原因從服務端請求到圖片路徑,要求通過該路徑擷取對應圖片的 base64 dataURL. 一個完整的 dataURI 應該是這樣的:

data:[<mediatype>][;base64],<data>

其中mediatype聲明了檔案類型,遵循MIME規則,如“image/png”、“text/plain”;之後是編碼類別型,這裡我們只涉及 base64;緊接著就是檔案編碼後的內容了。 我們常常在 HTML 裡看到img標籤的src會這樣寫:

src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7"

這個img引用的就是以 base64 編碼的 dataURL 了,只要瀏覽器支援,就可以被解碼成 gif 圖片並渲染出來。 或者在CSS中使用:
background-image:url("data:image/png;base64,iVBORw0KGgo=..."); 解決辦法:

FileReader對象也有類似的方法,比如.readAsDataURL(),然而它只接受file或blob類型,而這兩種類型一般只能通過<input[type=file]>元素的files屬性擷取,或者用Blob()建構函式手工建立一個新的對象。尷尬的是我們當前只有圖片路徑,受制於瀏覽器的安全性原則,<input[type=file]>的files屬性是唯讀,而Blob()建構函式只接受檔案內容,兩種方式都無法通過圖片路徑直接擷取。上文中假設的應用情境迫使我們必先考慮如何通過路徑擷取到圖片內容。<img>是可以的,並且可以被繪製到<canvas>中,而<canvas>正巧擁有.toDataURL()方法。

解決辦法一:canvas-toDataURL()

把擷取到的圖片放到裡再通過.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非同步事件中。現在就來實現一個功能函數:

function getBase64(url) {        //通過建構函式來建立的 img 執行個體,在賦予 src 值後就會立刻下載圖片,相比 createElement() 建立 <img> 省去了 append(),也就避免了文檔冗餘和汙染        var Img = new Image(),            dataURL = '';        Img.src = url;        Img.onload = function() { //要先確保圖片完整擷取到,這是個非同步事件            //建立canvas元素            var canvas = document.createElement("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        };        return dataURL;    }
跨域訪問圖片遇到的問題:

報錯:Uncaught SecurityError: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.

canvas繪製圖片,由於瀏覽器的安全考慮,如果在使用canvas繪圖的過程中,使用到了外域的圖片資源,那麼在toDataURL()時會拋出安全異常

解決方案1.

如果想使用toDataURL()產生圖片檔案的話,在canvas繪圖過程中使用的圖片應該是當前域下的。

解決方案2.

①訪問的伺服器允許,資源跨域使用,也就是說設定了CORS跨網域設定,Access-Control-Allow-Origin

②然後在用戶端訪問圖片資源的時候

var img = new Image();img.setAttribute('crossOrigin', 'anonymous');img.src = url;

一個完整的案例:

<!DOCTYPE html><html lang="en"><head>    <title>123</title>    <meta http-equiv="X-UA-Compatible" content="chrome=1">    <script>    window.onload = function() {          draw();          var saveButton = document.getElementById("saveImageBtn");          bindButtonEvent(saveButton, "click", saveImageInfo);          var dlButton = document.getElementById("downloadImageBtn");          bindButtonEvent(dlButton, "click", saveAsLocalImage);      };          function draw(){              var canvas = document.getElementById("thecanvas");              var ctx = canvas.getContext("2d");              ctx.fillStyle = "rgba(125, 46, 138, 0.5)";              ctx.fillRect(25,25,100,100);               ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";              ctx.fillRect(58, 74, 125, 100);              ctx.fillStyle = "rgba( 0, 0, 0, 1)"; // black color              ctx.fillText("Gloomyfish - Demo", 50, 50);          }          function bindButtonEvent(element, type, handler)          {                 if(element.addEventListener) {                    element.addEventListener(type, handler, false);                 } else {                    element.attachEvent('on'+type, handler);                 }          }          function saveImageInfo ()           {              var mycanvas = document.getElementById("thecanvas");              var image    = mycanvas.toDataURL("image/png");              console.log(image);            var w=window.open('about:blank','image from canvas');              w.document.write("<img src='"+image+"' alt='from canvas'/>");          }          function saveAsLocalImage () {              var myCanvas = document.getElementById("thecanvas");              // here is the most important part because if you dont replace you will get a DOM 18 exception.              var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream;Content-Disposition: attachment;filename=foobar.png");              // var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");               window.location.href=image; // it will save locally          }    </script></head><body bgcolor="#E6E6FA">    <div>        <canvas width=200 height=200 id="thecanvas"></canvas>        <button id="saveImageBtn">Save Image</button>        <button id="downloadImageBtn">Download Image</button>    </div>    </script> </body></html>

解決辦法二:FileReader的readAsDataURL()

參考連結:http://www.jianshu.com/p/17d7e5ddf10a
http://blog.csdn.net/jia20003/article/details/8948005
http://imgbase64.duoshitong.com/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.