二維碼與背景圖結合,并且能長按保存到本地相冊(即兩張圖片合成一張圖片)
需求場景:
在超級合伙人中或者服務化快推項目中,有一個功能是展示付唄APP下載二維碼,用戶可以通過掃一掃掃描下載二維碼進行下載;但是如果直接從后端傳圖片再顯示在性能與體驗上面會不太好,所以最終是二維碼+背景圖結合的方式來展示;開始的時候以為絕對定位分層顯示就好,但是另一個需求是可以長按識別二維碼,并且能保存圖片到本地相冊,僅僅憑借定位分層來布局肯定滿足不了這樣的需求,所以最終采用了canvas來合并圖片;
具體需求點:
- 需求1:
后端給一個下載的接口鏈接,二維碼前端生成;
- 需求2:
需要能夠長按圖片識別二維碼并且能原圖能保存到本地相冊;
解決方案:
- 需求1的解決方案:
首先將后端的接口進行拼接,然后用vue-qr 生成二維碼;(注意點:因為vue-qr是后期在頁面中生成二維碼的,所以直接在created或者mounted生命周期中去獲取二維碼鏈接(即轉換后的base64字符串)是獲取不到的,這時候需要在設置一定的延遲時間)
- 需求2的解決方案:
采用canvas來進行合成圖片;但是因為canvas繪圖時候會有跨域的問題,所以可以把背景圖存放在本地(static文件夾),另一種方案是用阿里云oss的圖片,但是服務器nginx需要配置阿里云oss圖片域名的反向代理;
- 具體實現代碼 初始化方法,合成成功后進行賦值
initImg () {
let codeUrl = document.getElementById('Qrcode').getElementsByTagName("img")[0].src,
bgImgUrl = './../../../static/image/downloadApp.png',
bgImgData;
this.loadImg(bgImgUrl).then((res)=>{
bgImgData = res;
return this.loadImg(codeUrl);
}).then((res) => {
this.bgImg = this.createCanvas(bgImgData.img, res.img, bgImgData.width, bgImgData.height);
this.isShow = false;
})
},
加載圖片,獲取上傳圖片的寬度、高度、大小
// url 需要繪制的圖片鏈接
loadImg (url) {
let image = new Image();
return new Promise( (resolve) => {
image.onload = function() {
resolve({
img: this,
width: image.width,
height: image.height
});
}
image.src = url; // 指定Image的路徑
});
},
加載圖片,獲取上傳圖片的寬度、高度、大小
// bgImg 背景圖片對像;codeImg 二維碼圖片對像;width 背景圖片寬度;height 背景圖片高度
createCanvas (bgImg, codeImg, width, height) {
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
canvas.style.width = width;
canvas.style.height = height;
ctx.drawImage(bgImg, 0, 0, width, height);
ctx.drawImage(codeImg, width*0.32, height*0.456, width*0.36, width*0.36);
return canvas.toDataURL('image/jpeg',1);
}