前端动态生成二维码后合成海报,下载分享
转载:zgh0711:https://blog.csdn.net/zgh0711/article/details/88192993
如何生成二维码
现在前端环境下,要生成二维码,可用的工具库有很多,我这里用的是 qrcode,首先安装
npm install --save qrcode
安装完之后 import 导入就能使用了
import QRCode from 'qrcode'
一,将生成的二维码通过 canvas 标签展示
1 | <canvas class = "qr" id= "qrCode-canvas" ></canvas> |
1 2 3 4 5 6 7 8 9 10 | let canvas = document.getElementById( 'qrCode-canvas' ) QRCode.toCanvas(canvas, this .qrCodeUrl, (error) => { if (error) { console.log(error) } else { canvas.style.width = '1.68rem' canvas.style.height = '1.68rem' }); } }) |
二维码生成好后,有需要的话可以调整下 canvas 的大小等属性,因为 qrcode 生成的二维码会带有一些默认样式,需要调整下。
二,先通过 canvas 生成二维码,然后将 canvas 的内容转为 base64 格式以 img 标签展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <img class = "qr" id= "qr-img" :src= "dataUrl" alt= "邀请二维码" /> let img = document.getElementById( 'qr-img' ) let canvas = document.createElement( 'canvas' ) canvas.width = img.width canvas.height = img.height //用 canvas 对象和邀请链接生成二维码,并将生成的二维码转为 base64 QRCode.toCanvas(canvas, this .qrCodeUrl, (error) => { if (error) { console.log(error) } else { this .dataUrl = canvas.toDataURL( "image/jpeg" ) }); } }) |
上面两种方式都可以生成二维码并显示在界面上,区别在于第一种是以 canvas 标签显示,在微信中长按是无法识别的。第二种是以 img 标签显示,在微信中长按会自动识别并可以直接以图片形式分享出去。
做到这一步,需求已经完成了一半,下一步就是按设计图要求把二维码定位到海报背景上,将二维码和海报合成为一张图片。之所以要合成为一张图片还是为了让用户在微信中操作方便。合成为一张图片后,用户在微信中直接长按合成后的海报就可以分享或者识别二维码。
合成海报时碰到的坑
合成海报时需要用到另一个工具库 html2canvas ,基本使用方法也很简单,先获取要合成图片的 dom 对象,然后调用 html2canvas ,它会返回一个 promise,里面的 canvas 就是合成后的图片信息,同样的,这里的 canvas 可以直接显示出来,也可以转成 base64 之后放到 img 标签里显示,但是为了分享或者下载方便,基本都是转成了 base64
1 2 3 4 | let poster = document.getElementById( 'poster' ) html2canvas(poster).then(canvas => { this .posterDataUrl = canvas.toDataURL() }); |
到这里,基本需求就完成了。然而世界上的事情往往都不会是一帆风顺的,在测试的时候发现出了问题。
我前面二维码是用上面说的第二种方法显示的,将二维码的 canvas 转成了 base64 显示在 img 标签上,再将这个二维码 img 和海报背景 img 合成。这样的实现方式在 iOS 和浏览器中都没有问题,然而在安卓版微信里面却是只有海报背景而没有二维码。
在查了N多资料和尝试了好多遍之后终于发现,是因为我的二维码是 base64 的,如果二维码是以 canvas 形式显示,再去合成海报,将合成后的海报转为 base64 就没有问题了。 所以我在前面写生成二维码的时候写了二种方法。至此,整个需求也就真正的完成了。
下面是完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <template> <div class = "ypl-flex" > <mt-header title= "邀请用户" go-back></mt-header> <div class = "invitePosterPage flex" > <p class = "title" >分享专属海报,邀请用户注册,即可成功邀请</p> <p class = "remark" >(注:只能通过此二维码注册用户才可成功邀请)</p> <img v- if = "posterDataUrl" :src= "posterDataUrl" class = "poster-bg" alt= "邀请海报" /> <div v- else id= "poster" class = "flex-row" style= "position: relative" > <img class = "poster-bg" src= "../../../assets/img/img_poster_bg.png" alt= "邀请海报背景" /> <canvas class = "qr" id= "qrCode-canvas" ></canvas> </div> </div> </div> </template> <script> /** * 这是邀请海报组件 */ import QRCode from 'qrcode' import html2canvas from 'html2canvas' ; export default { name: 'Poster' , data () { return { posterDataUrl: '' , qrCodeUrl: 'https://www.baidu.com' } }, async mounted () { this .createQRCode() }, methods: { createQRCode () { //先用 QRCode 生成二维码 canvas,然后用 html2canvas 合成整张海报并转成 base64 显示出来 let canvas = document.getElementById( 'qrCode-canvas' ) QRCode.toCanvas(canvas, this .qrCodeUrl, (error) => { if (error) { console.log(error) } else { //qrcode 生成的二维码会带有一些默认样式,需要调整下 canvas.style.width = '1.68rem' canvas.style.height = '1.68rem' let poster = document.getElementById( 'poster' ) html2canvas(poster).then(canvas => { this .posterDataUrl = canvas.toDataURL() }); } }) } }, } </script> |
这次做这个需求的过程中,查到了一些 html2canvas 的资料,有很多文章都提到 html2canvas 有一些坑,我是没碰到,现在将这些文章列出来,给需要的人。
html2canvas 用法详解
Html2canvas - 项目中遇到的那些坑点汇总(更新中…)
一次 H5 「保存页面为图片」 的踩坑之旅
微信H5实现网页长按保存图片及识别二维码
基于html2canvas实现网页保存为图片及图片清晰度优化
Vue.js结合Canvas制作二维码和图片的合成(qrcanvas + html2canvas)
然后就是 canvas 转 base64 的 .toDataURL()] 这个方法,这个方法里面其实是可以配置参数的,有需要的可以去看下这个文档
HTMLCanvasElement.toDataURL()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类