208 lines
4.3 KiB
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>
|