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 | 8 | import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus'; |
9 | 9 | import { toDataURL } from 'qrcode'; |
10 | 10 | import { downloadByUrl } from '/@/utils/file/download'; |
11 | + import { QrcodeDoneEventParams } from './types'; | |
11 | 12 | |
12 | 13 | export default defineComponent({ |
13 | 14 | name: 'QrCode', |
... | ... | @@ -38,10 +39,9 @@ |
38 | 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 | 43 | setup(props, { emit }) { |
43 | 44 | const wrapRef = ref<HTMLCanvasElement | HTMLImageElement | null>(null); |
44 | - const urlRef = ref<string>(''); | |
45 | 45 | async function createQrcode() { |
46 | 46 | try { |
47 | 47 | const { tag, value, options = {}, width, logo } = props; |
... | ... | @@ -58,8 +58,7 @@ |
58 | 58 | content: renderValue, |
59 | 59 | options: options || {}, |
60 | 60 | }); |
61 | - urlRef.value = url; | |
62 | - emit('done', url); | |
61 | + emit('done', { url, ctx: (wrapEl as HTMLCanvasElement).getContext('2d') }); | |
63 | 62 | return; |
64 | 63 | } |
65 | 64 | |
... | ... | @@ -70,8 +69,7 @@ |
70 | 69 | ...options, |
71 | 70 | }); |
72 | 71 | (unref(wrapRef) as HTMLImageElement).src = url; |
73 | - urlRef.value = url; | |
74 | - emit('done', url); | |
72 | + emit('done', { url }); | |
75 | 73 | } |
76 | 74 | } catch (error) { |
77 | 75 | emit('error', error); |
... | ... | @@ -81,7 +79,13 @@ |
81 | 79 | * file download |
82 | 80 | */ |
83 | 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 | 89 | if (!url) return; |
86 | 90 | downloadByUrl({ |
87 | 91 | url, | ... | ... |
src/components/Qrcode/src/types.ts
... | ... | @@ -31,3 +31,8 @@ export type ToCanvasFn = (options: RenderQrCodeParams) => Promise<unknown>; |
31 | 31 | export interface QrCodeActionType { |
32 | 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 | 58 | <CollapseContainer title="配置大小示例" class="text-center qrcode-demo-item"> |
59 | 59 | <QrCode :value="qrCodeUrl" :width="300" /> |
60 | 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 | 74 | </div> |
62 | 75 | </PageWrapper> |
63 | 76 | </template> |
... | ... | @@ -73,16 +86,36 @@ |
73 | 86 | components: { CollapseContainer, QrCode, PageWrapper }, |
74 | 87 | setup() { |
75 | 88 | const qrRef = ref<Nullable<QrCodeActionType>>(null); |
89 | + const qrDiyRef = ref<Nullable<QrCodeActionType>>(null); | |
76 | 90 | function download() { |
77 | 91 | const qrEl = unref(qrRef); |
78 | 92 | if (!qrEl) return; |
79 | 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 | 111 | return { |
112 | + onQrcodeDone, | |
82 | 113 | qrCodeUrl, |
83 | 114 | LogoImg, |
84 | 115 | download, |
116 | + downloadDiy, | |
85 | 117 | qrRef, |
118 | + qrDiyRef, | |
86 | 119 | }; |
87 | 120 | }, |
88 | 121 | }); | ... | ... |