前段時間遇到產品一個需求,在移動端上合成生成二維碼,并且合成背景圖和二維碼給用戶保存;
當時我在想,鏈接拼接生成二維碼這個沒什么,圖片合成在移動端來做,結果后端的小伙伴說他們有現成的方案,他們合成,最后也就讓后端做了;
最后想想,前端其實做起來也很方便啊,搞起!
-
兼容性,瀏覽器支持canvas,似乎這是最核心最低的門檻,自己確認了一下兼容性
形式一片大好
-
問題分析
合成,也就是將一個背景圖,一個二維碼圖放在一個容器內,那么canvas不是有一個drawImage可以把圖片給畫進去么?最后再照葫蘆畫瓢畫二維碼,最后toDataURL把base64編碼的圖片信息導出給img標簽不就OK啦!
// bgSize,qrSize為對應圖的尺寸
// bgUrl,qrUrl為對應圖的地址
// qrX,qrY為偏移值,target為你展示的img標簽的class或者id
const canvas = document.createElement("canvas");
if (canvas.getContext) {
canvas.width = bgSize;
canvas.height = bgSize;
let ctx = canvas.getContext('2d');
ctx.fillRect(0 ,0, bgSize, bgSize);
ctx.fillStyle='transparent';
ctx.fill();
let bgImg = new Image();
// bgImg.crossOrigin = "anonymous";
bgImg.src = bgUrl;
bgImg.addEventListener("load", ()=> {
ctx.drawImage(bgImg, 0, 0, bgSize, bgSize);
let qrImg = new Image();
// qrImg.crossOrigin = "anonymous";
qrImg.src = qrUrl;
qrImg.addEventListener("load", ()=> {
ctx.drawImage(qrImg, qrX, qrY, qrSize, qrSize);
document.querySelector(target).src = canvas.toDataURL("image/png");
});
});
};
結果報錯了
這是為什么呢?去搜索了很多,很多人說什么canvas不能使用跨域圖片,問題都集中在跨域上;
跨域說對了一半,并不是canvas不能使用跨域圖片,而是在用沒有跨域權限圖片導出信息時會報錯,Canvas確實是為了安全性考慮,當繪制了外部圖片后它會變成只可寫不可讀的狀態(tài),getImageData、toDataURL之類的試圖讀取數據的方法全都無法使用;
img.crossOrigin = "anonymous";
之后呢,其實也就是讓前端開啟了圖片的跨域使用,為圖片服務添加CROS(跨域)支持,具體方法是在圖片的返回的header中添加Access-Control-Allow-Origin:*,同時在請求圖片時,為image元素設置crossOrigin="" 屬性設置為空字符串或者 "anonymous",這樣就可以跨域導出圖片信息,也就是畫圖了;
這邊MDN上就介紹了這個啟用了 CORS 的圖片;