原文鏈接: http://lion1ou.win/2017/12/01/
需求
要用代碼來實現(xiàn)多張外部圖片和文字的合并而且要上傳到七牛云,再將圖片鏈接通過客戶端分享出去土浸。圖片背景需要支持用戶自定義更換橙凳。
實現(xiàn)方案
在一個canvas上多次調(diào)用drawImage函數(shù)蕾殴,分別繪制在canvas中,多次之后canvas中是多個圖片合并的效果岛啸,然后再調(diào)用toDataURL函數(shù)將canvas轉(zhuǎn)成dataURL格式的圖片钓觉,再將dataURL格式裝換為blob文件,上傳至七牛云坚踩。
需要注意的坑
canvas圖片模糊的問題
將canvas的長寬設(shè)為樣式長寬的2倍或更大荡灾, 如下:
var canvas = document.getElementById("myCanvas");
canvas.width = "600";
canvas.height = "600"
canvas.style.height = "300px"
canvas.style.height = "300px"
報安全性錯誤
如果你的圖片url和頁面不在同一域下,在調(diào)用toDataURL函數(shù)的時候就會報安全性錯誤瞬铸。chrome中:
Uncaught SecurityError: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.
Safari中貌似更嚴格批幌,根域名相同子域不同依然會報錯:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.
原因:
沒有CORS授權(quán)雖然可以在 canvas 中使用圖像, 但這樣做就會污染(taints)畫布。 只要 canvas 被污染, 就不能再從畫布中提取數(shù)據(jù), 也就是說不能再調(diào)用 toBlob(), toDataURL() 和 getImageData() 等方法, 否則會拋出安全錯誤(security error).這實際上是為了保護用戶的個人信息,避免未經(jīng)許可就從遠程web站點加載用戶的圖像信息,造成隱私泄漏嗓节。
解決方法:
為每個圖片創(chuàng)建一個新的img對象荧缘,再賦給其src等參數(shù),用這種方式要等到img加載完畢再進行canvas其他操作拦宣,在img的load事件處理函數(shù)中進行操作截粗,否則可能會繪制出空內(nèi)容信姓。
let img = new Image()
img.setAttribute('crossorigin', 'anonymous')
img.src = imgUrl
img.onload = function () {
// do Something
}
img.error = function () {}
在mac和pc的瀏覽器上運行正常,但是在ios11以下的手機內(nèi)無法toDataURL
解決辦法:
- 改變圖片的載入方式绸罗,先在DOM上新建img標簽财破,如下:
<img crossOrigin="Anonymous" id="bgImg" src="https://www.test.com/test.png" alt="">
注意:crossOrigin="Anonymous"
一定要在src
屬性前面
被這個坑了很久
- 利用js獲取img元素
var img = document.getElementById('bgImg')
ctx.drawImage(img, 0, 0, 700, 700)
canvas.toBlob() safari上無效
解決辦法:
將canvas使用toDataURL方法轉(zhuǎn)為base64,再將base64通過file API 轉(zhuǎn)為 blob
function dataURLtoBlob (dataurl) { // 將dataUrl 轉(zhuǎn)為 Blob
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {type: mime})
}
var resultBase64 = canvas.toDataURL('image/jpeg') // 轉(zhuǎn)為jpeg壓縮圖片大小
var canvasBlob = dataURLtoBlob(resultBase64)
轉(zhuǎn)載請標注原文地址