首先說下需求,一張海報圖片於一張前端生成的二維碼繪制出一幅海報來,二維碼生成的本質就是一張canvas,此時我們可以利用toDataURL方法將這張二維碼轉成base64
接着創建一個img標簽 讓其src等於這個base64,接着海報和二維碼就放在了兩張圖片中了,到了這步大家是不是覺得大功告成了可以美滋滋的畫圖了,豈不知一波坑就此襲來了~~~
第一個錯如下。。。。
Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
什么意思呢 其實由於同源策略的原因canvas被污染了,無法使用toDataURL去導出canvas的數據
此時有的小伙伴可能想到了,去設置跨域屬性img.setAttribute("crossOrigin",'anonymous');這個屬性吧,然后興高采烈的去嘗試發現還不行~~~~
所以這時候就要找你服務端小哥哥了,問下你們服務器是否設置被允許訪問了
到了這里大家肯定覺得終於行了,然后一試。。。。滿屏紅的跨域報錯信息又出來了。。。。此時來自一枚程序員無聲的吶喊掙扎中~~~
多次掙扎后終於找到解決方案 src屬性后面拼接一個時間戳就可以了!!!
內心反復不相信,多次嘗試后還真是這么狗就能出來~~~
function drawRoundRectPath(cxt, width, height, radius) { cxt.beginPath(0); //從右下角順時針繪制,弧度從0到1/2PI cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2); //矩形下邊線 cxt.lineTo(radius, height); //左下角圓弧,弧度從1/2PI到PI cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); //矩形左邊線 cxt.lineTo(0, radius); //左上角圓弧,弧度從PI到3/2PI cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2); //上邊線 cxt.lineTo(width - radius, 0); //右上角圓弧 cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2); //右邊線 cxt.lineTo(width, height - radius); cxt.closePath(); } function fillRoundRect(cxt, x, y, width, height, radius, fillColor) { //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 drawRoundRectPath(cxt, width, height, radius); cxt.fillStyle = fillColor || "#000"; //若是給定了值就用給定的值否則給予默認值 cxt.fill(); cxt.restore(); } const canvasQr = (posterCanvas, qrCanvas, poster, qrCodeCanvas, setImgW) => {//下載圖片地址和圖片名 return new Promise((resolve, reject) => { try { const posterCtx = posterCanvas.getContext('2d'); const qrCtx = qrCanvas.getContext('2d'); const img1: any = new Image(); const img2: any = new Image(); const newimg1: any = new Image(); img1.setAttribute('crossorigin', 'anonymous') img1.src = poster + "?" + new Date().getTime(); img1.onload = () => { setImgW({ width: img1.width, height: img1.height }) qrCtx.drawImage(img1, 0, 0, img1.width, img1.height); newimg1.src = qrCanvas.toDataURL(); newimg1.onload = () => { posterCtx.drawImage(qrCanvas, 0, 0, img1.width, img1.height); //帶圓角的白色矩形 fillRoundRect(posterCtx, img1.width - (img1.width / 3) - 18, img1.height - (img1.width / 3) - 40, (img1.width / 3), (img1.width / 3), 20, '#fff'); img2.src = qrCodeCanvas.toDataURL(); img2.onload = () => { posterCtx.drawImage(img2, img1.width - (img1.width / 3) - 8, img1.height - (img1.width / 3) - 30, (img1.width / 3) - 20, (img1.width / 3) - 20); resolve(posterCanvas.toDataURL()) }; } } } catch (error) { reject("error") } }) } export default canvasQr