先說下canvas繪圖的基本方法,以下:canvas
const myCanvas = document.createElement('canvas'); myCanvas.width = 400; myCanvas.height = 400; const ctx = myCanvas.getContext('2d'); const img = new Image(); img.src = "1.jpg"; //當圖片加載完畢的時候在drawImage,不然可能圖片尚未加載完畢 img.onload=()=>{ ctx.drawImage(img, 0, 0, 100, 50); }
語法:
drawImage(image, x, y)
以canvas上指定的座標點開始,按照圖像的原始尺寸大小繪製整個圖像。
drawImage(image, x, y, width, height)
以canvas上指定的座標點開始,以指定的大小(width和height)繪製整個圖像,圖像會自動縮放。
drawImage(image, imageX, imageY, imageWidth, imageHeight, x, y, width, height)
將指定圖像的局部圖像(以(imageX, imageY)爲左上角、寬度爲imageWidth、高度爲imageHeight的矩形部分)繪製到canvas中以( x, y)爲左上角座標、寬度爲width、高度爲height的矩形區域中
此次多圖拼合的業務場景是作不一樣內容的定製分享圖片,用到的圖片元素有,背景圖片、外鏈圖片、網站logo、定製生產的二維碼圖,須要解決的問題,都是在畫布轉圖片輸出時產出的。主要有3點:
一、圖片的跨域問題;
二、繪製多圖,形成的畫布污染;
三、圖片的大小;跨域
首先圖片的跨域問題,這個問題在網上已經有不少相關信息,解決辦法以下:網站
img.setAttribute('crossOrigin', 'anonymous');
當解決完跨域問題後,在多圖拼合導出後,出現了新的報錯信息:Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted Canvases may not be exported.
我發現這個問題時,查看網上的資料,大多也是用上面的跨域方法解決的,但是我明顯在個人業務場景裏是無論用的。
經過對代碼的排查,我發現,背景圖+二維碼圖時,並不會報這個錯誤,如外鏈圖片作了跨域處理,單獨使用時,也不會報錯。而logo圖片都是本地的文件,顯然不該該是跨域問題。
那麼二維碼圖和背景圖可以不出錯的緣由,應該在於二維碼圖片源是base64格式的。
因而,我試着將logo圖使用畫布導出base64格式,而後和背景圖+二維碼圖進行拼合,導出時果真沒再報錯。
全部解決多圖拼合導出時,Tainted Canvases的問題,應該是將圖片元素作成base64的格式,就可以避免了。
由於個人業務場景中有外鏈圖片,並且不是全部的外鏈都對我網站域名作了跨域容許的處理,因此,在生成外鏈圖片的base64數據時,但是使用img.onerror事件的處理,用缺省圖替換。code
由於有在畫總圖以前,有對多圖的分別處理,所以,使用Promise處理可能會更好一些。事件
在圖片導出的大小問題上,導出時儘可能使用圖片
myCanvas.toDataURL('image/jpeg', encoderOptions)
encoderOptions:能夠從0到1的區間內選擇圖片的質量。若是超出取值範圍,將會使用默認值 0.92。其餘參數會被忽略。
以上我的對canvas拼合多圖並導出圖片的經驗總結。get