Skip to content

Commit

Permalink
Merge pull request #111 from KuaiYu95/fix-qrcode
Browse files Browse the repository at this point in the history
fix: 修复二维码生成器无法清空内容的bug
  • Loading branch information
phxa1 authored Jan 10, 2024
2 parents f5a5d22 + 903d6fc commit 94a442a
Showing 1 changed file with 101 additions and 95 deletions.
196 changes: 101 additions & 95 deletions src/pages/generate_qrcode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ import { useEffect, useState } from 'react';
const OriginTypes = [
{ label: '文本', value: 'text' },
{ label: '网址', value: 'url' },
// { label: "文件", value: "file" },
// { label: "图片", value: "image" },
// { label: "音视频", value: "media" },
// { label: "名片", value: "card" },
// { label: "微信", value: "wechat" },
];

const LevelErrorResistance = {
L: '7%',
M: '15%',
Expand Down Expand Up @@ -88,59 +84,33 @@ const _C = () => {
document.body.removeChild(a);
};

const uploadBgi = () => {
const bgiInput = document.getElementById('bgiInput');
bgiInput?.click();
};

const uploadFgi = () => {
const fgiInput = document.getElementById('fgiInput');
fgiInput?.click();
};

const uploadLogo = () => {
const logoInput = document.getElementById('logoInput');
logoInput?.click();
};

const addBgi = (event: any) => {
const file = event.target.files[0];
const img = new Image();
const canvas = document.createElement('canvas');
img.src = URL.createObjectURL(file);
img.onload = () => {
canvas.width = options.width!;
canvas.height = options.width!;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0, options.width!, options.width!);
const bgiData = ctx?.getImageData(0, 0, options.width!, options.width!);
setBgcolor('#ffffff');
setBgimg(bgiData);
};
const upload = (type: string) => {
const input = document.getElementById(type);
input?.click();
};

const addFgi = (event: any) => {
const addGi = (event: any, type: 'bgimg' | 'fgimg' | 'logoimg') => {
const file = event.target.files[0];
const img = new Image();
const canvas = document.createElement('canvas');
img.src = URL.createObjectURL(file);
img.onload = () => {
if (type === 'logoimg') {
setLogo(img);
return;
}
canvas.width = options.width!;
canvas.height = options.width!;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0, options.width!, options.width!);
const fgiData = ctx?.getImageData(0, 0, options.width!, options.width!);
setFgcolor('#000000');
setFgimg(fgiData);
};
};

const addLogo = (event: any) => {
const file = event.target.files[0];
const img = new Image();
img.src = URL.createObjectURL(file);
img.onload = () => {
setLogo(img);
const data = ctx?.getImageData(0, 0, options.width!, options.width!);
if (type === 'bgimg') {
setBgcolor('#ffffff');
setBgimg(data);
} else {
setFgcolor('#000000');
setFgimg(data);
}
};
};

Expand All @@ -157,11 +127,19 @@ const _C = () => {

const deleteCanvas = () => {
clear();
setText('');
setUrl('');
const qrcodeCanvas = document.getElementById('qrcode') as HTMLCanvasElement;
const qrcodeCtx = qrcodeCanvas!.getContext('2d');
qrcodeCtx?.clearRect(0, 0, options.width!, options.width!);
setTimeout(() => {
clear();
setText('');
setUrl('');
const qrcodeCanvas = document.getElementById(
'qrcode'
) as HTMLCanvasElement;
const qrcodeCtx = qrcodeCanvas!.getContext('2d', {
willReadFrequently: true,
})!;
qrcodeCtx.clearRect(0, 0, options.width!, options.width!);
}, 0);
// requestAnimationFrame(deleteCanvas)
};

useEffect(() => {
Expand All @@ -177,7 +155,9 @@ const _C = () => {
const qrcodeCanvas = document.getElementById(
'qrcode'
) as HTMLCanvasElement;
const qrcodeCtx = qrcodeCanvas!.getContext('2d');
const qrcodeCtx = qrcodeCanvas!.getContext('2d', {
willReadFrequently: true,
})!;

if (bgcolor) {
for (let i = 0; i < qrcodePixels.length; i += 4) {
Expand Down Expand Up @@ -251,35 +231,39 @@ const _C = () => {
}
}

qrcodeCtx?.putImageData(qrcodeimg, 0, 0);
qrcodeCtx.putImageData(qrcodeimg, 0, 0);

if (logo) {
qrcodeCtx?.beginPath();
qrcodeCtx?.arc(
// 绘制外圆
qrcodeCtx.beginPath();
qrcodeCtx.arc(
options.width! / 2,
options.width! / 2,
(options.width! / 8 + 4) | 0,
0,
2 * Math.PI,
false
);
qrcodeCtx!.fillStyle = '#ffffff';
qrcodeCtx?.fill();
qrcodeCtx?.clip();
qrcodeCtx?.closePath();
qrcodeCtx?.beginPath();
qrcodeCtx?.arc(
qrcodeCtx.fillStyle = '#ffffff';
qrcodeCtx.fill();
qrcodeCtx.clip();
qrcodeCtx.closePath();

// 绘制内圆
qrcodeCtx.beginPath();
qrcodeCtx.arc(
options.width! / 2,
options.width! / 2,
(options.width! / 8) | 0,
0,
2 * Math.PI,
false
);
qrcodeCtx?.fill();
qrcodeCtx?.clip();
qrcodeCtx?.closePath();
qrcodeCtx?.drawImage(
qrcodeCtx.fill();
qrcodeCtx.clip();
qrcodeCtx.closePath();

qrcodeCtx.drawImage(
logo,
(options.width! * 3) / 8,
(options.width! * 3) / 8,
Expand All @@ -302,22 +286,20 @@ const _C = () => {
}, [oType]);

useEffect(() => {
setTimeout(() => {
const content = oType === 'text' ? text : url;
const qrcodeCanvas = document.getElementById(
'qrcode'
) as HTMLCanvasElement;
if (!qrcodeCanvas || !content) return;
QRCode.toCanvas(qrcodeCanvas, content, options);
const qrcodeCtx = qrcodeCanvas!.getContext('2d');
const qrcodeData = qrcodeCtx?.getImageData(
0,
0,
options.width!,
options.width!
);
setQrcodeData(qrcodeData!);
}, 200);
const content = oType === 'text' ? text : url;
const qrcodeCanvas = document.getElementById('qrcode') as HTMLCanvasElement;
if (!qrcodeCanvas || !content) return;
QRCode.toCanvas(qrcodeCanvas, content, options);
const qrcodeCtx = qrcodeCanvas!.getContext('2d', {
willReadFrequently: true,
})!;
const qrcodeData = qrcodeCtx.getImageData(
0,
0,
options.width!,
options.width!
);
setQrcodeData(qrcodeData!);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [options, bgimg, fgimg, bgcolor, fgcolor, logo, count]);

Expand All @@ -344,7 +326,7 @@ const _C = () => {
textarea: { height: '100% !important' },
}}
value={text}
rows={4}
rows={3}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setText(event.target.value)
}
Expand Down Expand Up @@ -393,14 +375,31 @@ const _C = () => {
{!!qrcodeData && (
<>
<Box sx={{ fontSize: '16px', fontWeight: 600, mb: 2 }}>Logo</Box>
<Button
variant='outlined'
sx={{ borderRadius: '4px', width: '120px' }}
size='small'
onClick={uploadLogo}
<Stack
direction={'row'}
alignItems={'center'}
spacing={2}
sx={{ fontSize: '14px' }}
>
上传 Logo
</Button>
<Button
variant='outlined'
sx={{ borderRadius: '4px', width: '120px' }}
size='small'
onClick={() => upload('logoInput')}
>
上传 Logo
</Button>
{!!logo && (
<Box
sx={{ color: 'error.main', cursor: 'pointer' }}
onClick={() => {
setLogo(undefined);
}}
>
清除
</Box>
)}
</Stack>
<Box sx={{ fontSize: '16px', fontWeight: 600, mb: 2 }}>颜色</Box>
<Stack
direction={'row'}
Expand Down Expand Up @@ -432,7 +431,7 @@ const _C = () => {
variant='outlined'
sx={{ borderRadius: '4px', width: '120px' }}
size='small'
onClick={uploadBgi}
onClick={() => upload('bgiInput')}
>
{!!bgimg ? '更换背景图' : '上传背景图'}
</Button>
Expand Down Expand Up @@ -478,7 +477,7 @@ const _C = () => {
variant='outlined'
sx={{ borderRadius: '4px', width: '120px' }}
size='small'
onClick={uploadFgi}
onClick={() => upload('fgiInput')}
>
{!!fgimg ? '更换前景图' : '上传前景图'}
</Button>
Expand Down Expand Up @@ -581,6 +580,13 @@ const _C = () => {
{options.width}x{options.width}px
</Box>
<Stack direction={'row'} spacing={2}>
<Button
variant='outlined'
sx={{ borderRadius: '4px', width: '100%' }}
onClick={clear}
>
清除美化
</Button>
<Button
variant='outlined'
sx={{ borderRadius: '4px', width: '100%' }}
Expand Down Expand Up @@ -616,23 +622,23 @@ const _C = () => {
type='file'
accept='image/*'
style={{ display: 'none' }}
onChange={addBgi}
onChange={(event) => addGi(event, 'bgimg')}
/>
<Box
component={'input'}
id='fgiInput'
type='file'
accept='image/*'
style={{ display: 'none' }}
onChange={addFgi}
onChange={(event) => addGi(event, 'fgimg')}
/>
<Box
component={'input'}
id='logoInput'
type='file'
accept='image/*'
style={{ display: 'none' }}
onChange={addLogo}
onChange={(event) => addGi(event, 'logoimg')}
/>
</Stack>
</MainContent>
Expand Down

0 comments on commit 94a442a

Please sign in to comment.