canvas生成二維碼附帶icon並實現下載
https://blog.csdn.net/chy555chy/article/details/85785819
利用 qrcode 生成二維碼是不帶 icon
的,去網上查找解決方案需要修改源碼。
所以只好自己開搞了
效果如下:
代碼如下
<template>
<div>
<!-- 二維碼和icon -->
<img :src="rediusIconSrc" alt="ICON">
<img :src="qrCodeSrc" alt="qrcode">
<img :src="iconCodeSrc" alt="IconAndQrcode">
<button @click="getQrcode">下載</button>
</div>
</template>
<script>
import QRCode from 'qrcode'; // 需安裝 qrcode 插件;
export default {
data() {
return {
qrCodeSrc: '',
rediusIconSrc: '',
iconCodeSrc: '',
qrCodeW: '200',
qrCodeH: '200',
codeContext: 'text123',
iconScale: 0.2 // icon 佔二維碼的比例;
};
},
mounted() {
this.getCanvas(this.codeContext);
},
methods: {
getQrcode() {
let _a = document.createElement('a');
_a.href = this.iconCodeSrc;
_a.download = '帶有 icon 的二維碼';
_a.click();
},
getCanvas(codeContext, option = {errorCorrectionLevel: 'H', margin: 1}) {
// 配置參數 參考https://github.com/soldair/node-qrcode#options
// var opts = {
// errorCorrectionLevel: 'H', // 容錯級別 low, medium, quartile, high or L, M, Q, H.
// type: 'image/jpeg', // 圖片類型
// quality: 0.9, // 透明度 貌似沒啥效果
// maskPattern: 1, // 遮罩圖案
// margin: 1, // 二維碼距離邊框的距離 單位爲4px 默認值1個單位
// color: { // 二維碼 碼塊的顏色
// dark: '#010599FF', // 默認值 #000000
// light: '#FFBF60FF' // 默認值 #ffffff
// }
// };
QRCode.toDataURL(codeContext, option, (err, url) => {
if (err) throw err;
// 生成二維碼圖片地址
this.qrCodeSrc = url;
// 二維碼 轉化爲 canvas 並將 icon 畫入到 canvas 中,然後導出;
this.addicon();
});
},
// 生成帶邊框及圓角的 icon 圖片;
addicon(X = 0, Y = 0, W, H, radius = 5, birderW = 2, borderColor = '#fff', isbgColor = true, bgColor = 'rgba(255,255,255, 1)') {
let c = document.createElement('canvas');
c.width = this.qrCodeW * this.iconScale;
c.height = this.qrCodeH * this.iconScale;
let _w = W || c.width, _h = H || c.height;
let ctx = c.getContext('2d');
// 是否設置背景顏色
if (isbgColor) {
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, c.width, c.height);
}
this.drawRoundRect(ctx, X, Y, _w, _h, radius, birderW, borderColor);
let img = document.createElement('img');
// 網絡圖片直接給地址;
img.src = 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2069790559,642682254&fm=26&gp=0.jpg';
// 如果是本地圖片請使用 require() 引入;
// img.src = require(src); // src 不能使變量 會查找不到;
// 解決 訪問網絡圖片屬於跨域操作 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
img.setAttribute('crossOrigin', 'Anonymous');
img.onload = () => {
ctx.clip();
ctx.drawImage(img, 0, 0, 40, 40);
ctx.restore();
this.rediusIconSrc = c.toDataURL();
this.mergeImg();
};
},
// 圓角 icon 和 二維碼 合併到一起;
mergeImg() {
let c = document.createElement('canvas');
c.width = this.qrCodeW;
c.height = this.qrCodeH;
let ctx = c.getContext('2d');
let bg = document.createElement('img');
let icon = document.createElement('img');
bg.src = this.qrCodeSrc;
icon.src = this.rediusIconSrc;
let _bgLoad = new Promise((resolve, reject) => {
try {
bg.onload = () => resolve();
} catch (error) {
reject(error);
}
});
let _iconLoad = new Promise((resolve, reject) => {
try {
icon.onload = () => resolve();
} catch (error) {
reject(error);
}
});
Promise.all([_bgLoad, _iconLoad]).then(res => {
let w = this.qrCodeW;
let h = this.qrCodeH;
let iconW = w * this.iconScale;
let iconH = h * this.iconScale;
let iconX = (w - iconW) / 2;
let iconY = (h - iconH) / 2;
// 畫二維碼
ctx.drawImage(bg, 0, 0, w, h);
// 畫icon
ctx.drawImage(icon, iconX, iconY, iconW, iconH);
// 轉化爲圖片 src;
this.iconCodeSrc = c.toDataURL();
}).catch(e => {
console.log('error-', e);
});
},
// 畫圓角 ctx 上下文 x,y 起始位置 width,height icon的寬高 radius 圓角的角度 lineWidth 邊框的寬度 lineColor 邊框的顏色
drawRoundRect(ctx, x, y, width, height, radius, lineWidth, lineColor) {
ctx.lineWidth = lineWidth;
ctx.strokeStyle = lineColor;
ctx.beginPath();
ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
ctx.lineTo(width - radius + x, y);
ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(width + x, height + y - radius);
ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2);
ctx.lineTo(radius + x, height + y);
ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI);
ctx.closePath();
ctx.stroke();
}
}
};
</script>