jiuyiUniapp/shop/components/rf-qrcode/index.vue

208 lines
4.3 KiB
Vue

<template>
<view>
<image v-if="filePath" :src="filePath" :style="{ width: `${size}px`, height: `${size}px` }"></image>
<canvas
v-if="!filePath"
:id="cid"
:canvas-id="cid"
:style="{ width: `${size}px`, height: `${size}px` }"
/>
</view>
</template>
<script>
import uQRCode from '@/utils/uqrcode.js';
export default {
props: {
cid: {
type: String,
required: true
},
text: {
type: String,
required: true
},
size: {
type: Number,
default: 129
},
margin: {
type: Number,
default: 0
},
backgroundColor: {
type: String,
default: '#ffffff'
},
foregroundColor: {
type: String,
default: '#000000'
},
backgroundImage: {
type: String
},
logo: {
type: String
},
makeOnLoad: {
type: Boolean,
default: false
}
},
data() {
return {
filePath: ''
};
},
mounted() {
if (this.makeOnLoad) {
this.make();
}
},
methods: {
async make() {
const options = {
canvasId: this.cid,
componentInstance: this,
text: this.text,
size: this.size,
margin: this.margin,
backgroundColor: this.backgroundImage
? 'rgba(255,255,255,0)'
: this.backgroundColor,
foregroundColor: this.foregroundColor
};
let filePath = await this.makeSync(options);
if (this.backgroundImage) {
filePath = await this.drawBackgroundImageSync(filePath);
}
if (this.logo) {
filePath = await this.drawLogoSync(filePath);
}
this.filePath = filePath;
this.makeComplete(filePath);
},
makeComplete(filePath) {
this.$emit('makeComplete', filePath);
},
drawBackgroundImage(options) {
const ctx = uni.createCanvasContext(this.cid, this);
ctx.drawImage(this.backgroundImage, 0, 0, this.size, this.size);
ctx.drawImage(options.filePath, 0, 0, this.size, this.size);
ctx.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: this.cid,
success: res => {
options.success && options.success(res.tempFilePath);
},
fail: error => {
options.fail && options.fail(error);
}
});
});
},
async drawBackgroundImageSync(filePath) {
return new Promise((resolve, reject) => {
this.drawBackgroundImage({
filePath: filePath,
success: res => {
resolve(res);
},
fail: error => {
reject(error);
}
});
});
},
fillRoundRect(ctx, r, x, y, w, h) {
ctx.save();
ctx.translate(x, y);
ctx.beginPath();
ctx.arc(w - r, h - r, r, 0, Math.PI / 2);
ctx.lineTo(r, h);
ctx.arc(r, h - r, r, Math.PI / 2, Math.PI);
ctx.lineTo(0, r);
ctx.arc(r, r, r, Math.PI, (Math.PI * 3) / 2);
ctx.lineTo(w - r, 0);
ctx.arc(w - r, r, r, (Math.PI * 3) / 2, Math.PI * 2);
ctx.lineTo(w, h - r);
ctx.closePath();
ctx.setFillStyle('#ffffff');
ctx.fill();
ctx.restore();
},
drawLogo(options) {
const ctx = uni.createCanvasContext(this.cid, this);
ctx.drawImage(options.filePath, 0, 0, this.size, this.size);
const logoSize = this.size / 4;
const logoX = this.size / 2 - logoSize / 2;
const logoY = logoX;
const borderSize = logoSize + 10;
const borderX = this.size / 2 - borderSize / 2;
const borderY = borderX;
const borderRadius = 5;
this.fillRoundRect(
ctx,
borderRadius,
borderX,
borderY,
borderSize,
borderSize
);
ctx.drawImage(this.logo, logoX, logoY, logoSize, logoSize);
ctx.draw(false, () => {
uni.canvasToTempFilePath({
canvasId: this.cid,
success: res => {
options.success && options.success(res.tempFilePath);
},
fail: error => {
options.fail && options.fail(error);
}
});
});
},
async drawLogoSync(filePath) {
return new Promise((resolve, reject) => {
this.drawLogo({
filePath: filePath,
success: res => {
resolve(res);
},
fail: error => {
reject(error);
}
});
});
},
async makeSync(options) {
return new Promise((resolve, reject) => {
uQRCode.make({
canvasId: options.canvasId,
componentInstance: options.componentInstance,
text: options.text,
size: options.size,
margin: options.margin,
backgroundColor: options.backgroundColor,
foregroundColor: options.foregroundColor,
success: res => {
resolve(res);
},
fail: error => {
reject(error);
}
});
});
}
}
};
</script>