Commit 2b76b88481dab2c580e684987a80028710d4698d
Committed by
GitHub
1 parent
9d195462
feat(qrcode): custom drawing support (#580)
Showing
3 changed files
with
49 additions
and
7 deletions
src/components/Qrcode/src/index.vue
@@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
8 | import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus'; | 8 | import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus'; |
9 | import { toDataURL } from 'qrcode'; | 9 | import { toDataURL } from 'qrcode'; |
10 | import { downloadByUrl } from '/@/utils/file/download'; | 10 | import { downloadByUrl } from '/@/utils/file/download'; |
11 | + import { QrcodeDoneEventParams } from './types'; | ||
11 | 12 | ||
12 | export default defineComponent({ | 13 | export default defineComponent({ |
13 | name: 'QrCode', | 14 | name: 'QrCode', |
@@ -38,10 +39,9 @@ | @@ -38,10 +39,9 @@ | ||
38 | validator: (v: string) => ['canvas', 'img'].includes(v), | 39 | validator: (v: string) => ['canvas', 'img'].includes(v), |
39 | }, | 40 | }, |
40 | }, | 41 | }, |
41 | - emits: { done: (url: string) => !!url, error: (error: any) => !!error }, | 42 | + emits: { done: (data: QrcodeDoneEventParams) => !!data, error: (error: any) => !!error }, |
42 | setup(props, { emit }) { | 43 | setup(props, { emit }) { |
43 | const wrapRef = ref<HTMLCanvasElement | HTMLImageElement | null>(null); | 44 | const wrapRef = ref<HTMLCanvasElement | HTMLImageElement | null>(null); |
44 | - const urlRef = ref<string>(''); | ||
45 | async function createQrcode() { | 45 | async function createQrcode() { |
46 | try { | 46 | try { |
47 | const { tag, value, options = {}, width, logo } = props; | 47 | const { tag, value, options = {}, width, logo } = props; |
@@ -58,8 +58,7 @@ | @@ -58,8 +58,7 @@ | ||
58 | content: renderValue, | 58 | content: renderValue, |
59 | options: options || {}, | 59 | options: options || {}, |
60 | }); | 60 | }); |
61 | - urlRef.value = url; | ||
62 | - emit('done', url); | 61 | + emit('done', { url, ctx: (wrapEl as HTMLCanvasElement).getContext('2d') }); |
63 | return; | 62 | return; |
64 | } | 63 | } |
65 | 64 | ||
@@ -70,8 +69,7 @@ | @@ -70,8 +69,7 @@ | ||
70 | ...options, | 69 | ...options, |
71 | }); | 70 | }); |
72 | (unref(wrapRef) as HTMLImageElement).src = url; | 71 | (unref(wrapRef) as HTMLImageElement).src = url; |
73 | - urlRef.value = url; | ||
74 | - emit('done', url); | 72 | + emit('done', { url }); |
75 | } | 73 | } |
76 | } catch (error) { | 74 | } catch (error) { |
77 | emit('error', error); | 75 | emit('error', error); |
@@ -81,7 +79,13 @@ | @@ -81,7 +79,13 @@ | ||
81 | * file download | 79 | * file download |
82 | */ | 80 | */ |
83 | function download(fileName?: string) { | 81 | function download(fileName?: string) { |
84 | - const url = unref(urlRef); | 82 | + let url = ''; |
83 | + const wrapEl = unref(wrapRef); | ||
84 | + if (wrapEl instanceof HTMLCanvasElement) { | ||
85 | + url = wrapEl.toDataURL(); | ||
86 | + } else if (wrapEl instanceof HTMLImageElement) { | ||
87 | + url = wrapEl.src; | ||
88 | + } | ||
85 | if (!url) return; | 89 | if (!url) return; |
86 | downloadByUrl({ | 90 | downloadByUrl({ |
87 | url, | 91 | url, |
src/components/Qrcode/src/types.ts
@@ -31,3 +31,8 @@ export type ToCanvasFn = (options: RenderQrCodeParams) => Promise<unknown>; | @@ -31,3 +31,8 @@ export type ToCanvasFn = (options: RenderQrCodeParams) => Promise<unknown>; | ||
31 | export interface QrCodeActionType { | 31 | export interface QrCodeActionType { |
32 | download: (fileName?: string) => void; | 32 | download: (fileName?: string) => void; |
33 | } | 33 | } |
34 | + | ||
35 | +export interface QrcodeDoneEventParams { | ||
36 | + url: string; | ||
37 | + ctx?: CanvasRenderingContext2D | null; | ||
38 | +} |
src/views/demo/comp/qrcode/index.vue
@@ -58,6 +58,19 @@ | @@ -58,6 +58,19 @@ | ||
58 | <CollapseContainer title="配置大小示例" class="text-center qrcode-demo-item"> | 58 | <CollapseContainer title="配置大小示例" class="text-center qrcode-demo-item"> |
59 | <QrCode :value="qrCodeUrl" :width="300" /> | 59 | <QrCode :value="qrCodeUrl" :width="300" /> |
60 | </CollapseContainer> | 60 | </CollapseContainer> |
61 | + | ||
62 | + <CollapseContainer title="扩展绘制示例" class="text-center qrcode-demo-item"> | ||
63 | + <QrCode | ||
64 | + :value="qrCodeUrl" | ||
65 | + :width="200" | ||
66 | + :options="{ margin: 5 }" | ||
67 | + ref="qrDiyRef" | ||
68 | + :logo="LogoImg" | ||
69 | + @done="onQrcodeDone" | ||
70 | + /> | ||
71 | + <a-button class="mb-2" type="primary" @click="downloadDiy"> 下载 </a-button> | ||
72 | + <div class="msg"> 要进行扩展绘制则不能将tag设为img </div> | ||
73 | + </CollapseContainer> | ||
61 | </div> | 74 | </div> |
62 | </PageWrapper> | 75 | </PageWrapper> |
63 | </template> | 76 | </template> |
@@ -73,16 +86,36 @@ | @@ -73,16 +86,36 @@ | ||
73 | components: { CollapseContainer, QrCode, PageWrapper }, | 86 | components: { CollapseContainer, QrCode, PageWrapper }, |
74 | setup() { | 87 | setup() { |
75 | const qrRef = ref<Nullable<QrCodeActionType>>(null); | 88 | const qrRef = ref<Nullable<QrCodeActionType>>(null); |
89 | + const qrDiyRef = ref<Nullable<QrCodeActionType>>(null); | ||
76 | function download() { | 90 | function download() { |
77 | const qrEl = unref(qrRef); | 91 | const qrEl = unref(qrRef); |
78 | if (!qrEl) return; | 92 | if (!qrEl) return; |
79 | qrEl.download('文件名'); | 93 | qrEl.download('文件名'); |
80 | } | 94 | } |
95 | + function downloadDiy() { | ||
96 | + const qrEl = unref(qrDiyRef); | ||
97 | + if (!qrEl) return; | ||
98 | + qrEl.download('Qrcode'); | ||
99 | + } | ||
100 | + | ||
101 | + function onQrcodeDone({ ctx }) { | ||
102 | + if (ctx instanceof CanvasRenderingContext2D) { | ||
103 | + // 额外绘制 | ||
104 | + ctx.fillStyle = 'black'; | ||
105 | + ctx.font = '16px "微软雅黑"'; | ||
106 | + ctx.textBaseline = 'bottom'; | ||
107 | + ctx.textAlign = 'center'; | ||
108 | + ctx.fillText('你帅你先扫', 100, 195, 200); | ||
109 | + } | ||
110 | + } | ||
81 | return { | 111 | return { |
112 | + onQrcodeDone, | ||
82 | qrCodeUrl, | 113 | qrCodeUrl, |
83 | LogoImg, | 114 | LogoImg, |
84 | download, | 115 | download, |
116 | + downloadDiy, | ||
85 | qrRef, | 117 | qrRef, |
118 | + qrDiyRef, | ||
86 | }; | 119 | }; |
87 | }, | 120 | }, |
88 | }); | 121 | }); |