这次对(限时二维码跳转)工具做了两块体验与架构上的升级:二维码生成不再依赖外部生成服务,而是直接在浏览器内生成并二次绘制为“海报图”;二维码识别从服务端转发识别改为前端 `ZXing-WASM` 识别,并在识别到多条内容时让用户选择填入。体验地址:https://yangjinyou.com/page/dwz/
1.为什么要改
原来二维码生码与解码方案会遇到这些问题:
- 生成二维码依赖外部 API:网络波动、配额/签名、第三方不可用都会影响体验。
- “标题/有效期”如果靠外部二维码服务去排版,样式与可控性受限。
- 识别二维码如果走服务端代理上传图片:慢、占带宽、还涉及隐私(用户上传图像到服务端/第三方)。
因此本次改造目标很明确:
- 生成:完全前端生成,并把标题放上方、有效期放下方,合成一张可保存的 PNG。
- 识别:完全前端识别,页面加载时异步拉起 wasm 识别能力;支持“一张图里多个二维码内容”的选择填入。
2. 二维码生成:从“外部服务生成”到“前端生成 + 二次绘制海报图”
2.1 依赖:使用上一次制作的二维码生成器,配置生成的二维码渲染脚本[qrcode-config.js],它提供了全局方法:
generateQrCode(canvasId, content):把 content 渲染成二维码到指定 canvas
2.2 海报合成:新增 qrcode-poster.js
为了把“标题/有效期”绘制到二维码上下方,又不修改 [qrcode-config.js](后期可使用二维码生成器随时更改二维码样式),新增了独立脚本 [qrcode-poster.js],它的作用是:
- 用一个临时 canvas 调用
generateQrCode得到二维码图像 - 再创建一张“海报 canvas”
- 在海报 canvas 上绘制:
- 标题(上方,支持自动换行)
- 二维码(中间)
- 有效期(下方,支持自动换行)
- 输出 PNG DataURL(用于直接展示或下载)
2.3 交互接入:二维码模态框展示逻辑
- 点击“二维码”按钮后,会调用
dwzGenerateQrPoster生成 DataURL 并赋给<img id="qrImage">展示。 - 标题为空则不绘制标题:
title为空字符串时,海报上方不留标题区块。 - 移除二维码缓存:不再读写
qrimg/,也不再调用proxy.php?act=save_qr保存缓存;每次点击即时生成即时展示。(原有API生成二维码方案为减少请求次数,做了PNG图片缓存)
3. 微信上“保存图片”提示优化
很多移动端(尤其微信内置浏览器)对 <a download> 的支持并不理想。为避免用户误以为“下载失败”,在二维码模态框的“保存图片”按钮点击时做了 UA 判断:
- 如果是微信:提示
微信访问无法下载,请长按二维码保存或分享 - 非微信:保持原下载逻辑
4. 二维码识别:改为 ZXing-WASM 本地识别,并支持多结果选择(为何选择使用ZXing-WASM而不是其它前端库,有空再写一篇文章来说说)
4.1 目标:识别按钮不再走服务端代理
链接输入框右下角“识别二维码”按钮,原来是上传图片到服务端/第三方识别接口。现在改为直接使用 ZXing-WASM 在浏览器内识别。
识别核心脚本来自指定的:
[zxing-wasm/app.js]此脚本包含调用ZXing-WASM进行识别的方法配置及引用引用脚本库。
4.2 接入方式:页面加载时异步加载 app.js,为了让页面首屏更轻:
- 页面加载后异步插入
zxing-wasm/app.js(避免阻塞渲染) - 同时补齐它运行所需的 DOM(
file/retry/clear/out/c),但这些元素都被隐藏并放到页面外
4.3 识别多二维码:弹出选择模态框,选中后填入输入框
app.js 的输出是把识别结果写入 #out(textarea),当图片里有多个二维码时,它会用换行拼接多个内容。
因此新增了一个“选择识别结果”的模态框:
- 展示每一条识别到的内容(列表按钮)
- 用户点击某条后,把该内容填入目标输入框(主输入框或编辑输入框)
文章评论