|
|
@@ -0,0 +1,89 @@
|
|
|
+<template>
|
|
|
+ <canvas ref="canvasRef"></canvas>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { shallowRef, onMounted } from 'vue'
|
|
|
+import { fillRoundRect } from '@/utils/canvas'
|
|
|
+import QRCode from 'qrcode'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: String,
|
|
|
+ text: {
|
|
|
+ type: String,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ width: {
|
|
|
+ type: Number,
|
|
|
+ default: 320
|
|
|
+ },
|
|
|
+ margin: {
|
|
|
+ type: Number,
|
|
|
+ default: 2
|
|
|
+ },
|
|
|
+ logo: String,
|
|
|
+ logoWidth: Number,
|
|
|
+ logoBackground: String,
|
|
|
+})
|
|
|
+
|
|
|
+const emit = defineEmits(['update:modelValue'])
|
|
|
+const canvasRef = shallowRef<HTMLCanvasElement>()
|
|
|
+
|
|
|
+// const getImageBlob = (url: string) => {
|
|
|
+// return new Promise<string>((resolve, reject) => {
|
|
|
+// const xhr = new XMLHttpRequest()
|
|
|
+// xhr.open('GET', url, true)
|
|
|
+// xhr.responseType = 'blob'
|
|
|
+// xhr.onload = () => {
|
|
|
+// if (xhr.status === 200) {
|
|
|
+// resolve(URL.createObjectURL(xhr.response))
|
|
|
+// } else {
|
|
|
+// reject(xhr.statusText)
|
|
|
+// }
|
|
|
+// }
|
|
|
+// xhr.send()
|
|
|
+// })
|
|
|
+// }
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ const canvas = canvasRef.value
|
|
|
+ if (canvas) {
|
|
|
+ QRCode.toCanvas(canvas, props.text, { width: props.width, margin: props.margin, })
|
|
|
+ const drawQRcodeLogo = (imageSrc: string, crossOrigin = true) => {
|
|
|
+ return new Promise<void>((resolve) => {
|
|
|
+ const image = new Image()
|
|
|
+ if (crossOrigin) {
|
|
|
+ image.crossOrigin = 'Anonymous'
|
|
|
+ }
|
|
|
+ image.src = imageSrc
|
|
|
+ image.onload = () => {
|
|
|
+ const ctx = canvas.getContext('2d')
|
|
|
+ if (ctx) {
|
|
|
+ // 绘制背景
|
|
|
+ const width = props.logoWidth ?? 56 // 背景宽高
|
|
|
+ const x = (canvas.width - width) / 2
|
|
|
+ const y = (canvas.height - width) / 2
|
|
|
+ fillRoundRect(ctx, x, y, width, width, 8, props.logoBackground ?? '#fff')
|
|
|
+ // 插入图像
|
|
|
+ const imageWidth = width * 0.9 // 图像宽高
|
|
|
+ const dx = (canvas.width - imageWidth) / 2
|
|
|
+ const dy = (canvas.height - imageWidth) / 2
|
|
|
+ ctx.drawImage(image, dx, dy, imageWidth, imageWidth)
|
|
|
+ }
|
|
|
+ resolve()
|
|
|
+ }
|
|
|
+ image.onerror = async () => {
|
|
|
+ resolve()
|
|
|
+ if (crossOrigin) {
|
|
|
+ drawQRcodeLogo(imageSrc, false)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (props.logo) {
|
|
|
+ await drawQRcodeLogo(props.logo)
|
|
|
+ }
|
|
|
+ emit('update:modelValue', canvas.toDataURL())
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|