前端如何优雅的制作带LOGO的二维码

说在前面的话...

最近项目有个功能产品列表,可以将不同产品生成不同的二维码,扫码可以进入对应的产品详情页,同时二维码需要带公司logo,需要可以长按调起微信的下载图片的功能,其实也就是说,最后生成的二维码是一个图片

首先介绍一个比较出名的生成二维码的插件QRcode

  1. 这个插件是基于jq封装的所以在使用时需要先引入jq
  2. 用法也比较简单 直接上代码
<div id="qrcode" class="qrcode clip"></div>
<canvas id="myCanvas" width="200" height="200" class="qrcode clip"></canvas>
<img id="canvasImg" alt="" width="200" height="200" class="qrcode">
let src = "/static/imgs/settle.png"; //想显示的二维码中间的图片
$("#qrcode").qrcode({
 	render: "canvas", //设置渲染方式,有table和canvas,使用canvas方式渲染性能相对来说比较好
	text: ``, //扫描二维码后显示的内容,可以直接填一个网址,扫描二维码后自动跳向该链接
	width: "200", //二维码的宽度
	height: "200", //二维码的高度
	background: "#ffffff", //二维码的后景色
	foreground: "#000000", //二维码的前景色
	src: src //二维码中间的图片
});
复制代码

这样操作大家会发现已经显示了带logo的二维码,细心的同学会发现,当我们在手机中打开页面时,并不能调起长按保存二维码,原因是我们拿插件生成是canvas并不是img,所以后面我们要进入真正的主题,利用canvas生成图片

利用canvas生成图片

  • 首先整理一下思路,从上面的方法中我们已经得到了canvas ,那canvas可不可以直接转成图片呢
  • 引入canvas.toDataURL(),这个方法是将canvas转化成base64,base64可以作为img的src,就可以成功的将canvas转化成图片,参数我们可以定义是想转化为何种形式的图片,我这里用的toDataURL("image/png")
    convertCanvasToImage() {
        var canvas = $("#qrcode canvas")[0].toDataURL("image/png")
        return canvas
     }
    复制代码
  • 但是当我们转化完成之后却发现,转化出来的base64展示出来只是一张二维码,并没有logo,我分析应该插件没有真正的将logo合成上去,我们需要将logo和base64合成一张图片,所以需要利用canvas合成图片

利用canvas合成图片

  • 那么首先我们整理一下思路,其实我们要做的就是利用canvas的drawImage画图片功能先后将base64.和logo画上去,最后再一起转成base64
  • 这里有一个问题是画图时我们是需要用到img.onload方法,而这个方法是异步,且需要本地服务支持,有些同学可能会在本地静态页面写demo ,却展示不出最后合成的base64,就是因为无服务的原因。所以需要利用node,或者放在类似vue ng 这类项目中 看效果
export function creatEwm(base64, canvas,callback) {
 var ctx = canvas.getContext("2d");
 var img = document.createElement('img');
 img.src = '/static/imgs/icon-phone.png'
 img.onload = function () {
   var imgUpload = new Image();
   imgUpload.src = base64();
   imgUpload.onload = function () {
     // 绘制
     ctx.drawImage(imgUpload, 0, 0, 200, 200);
     ctx.drawImage(img, 78, 80, 40, 40);
     callback(canvas.toDataURL("image/png"))
   };
 }
}
复制代码
  • 上面我封装了一下生成最后base64的方法
  • 参数一base64是我们第一次拿qrcode生成二维码的base64也就是我上面写的convertCanvasToImage方法的返回值
  • 参数二是获取到的需要绘制的canvas的节点,这里与qrcode 的节点不同 需从新定义,也就是我在最开始定义id为myCanvas的canvas标签
  • 参数三是传回调,因为上面讲到,img.onload是异步加载,我们是拿不到最后的base64,可以通过回调的方式获取到异步数据,当然也可以用promise等方式
  • 方法中,引入了需要的logo 但此次并没有任何地方承载这个图片。所以我们需要新建一个空img标签去承载,后面才可以用drawImage方法,当然用new Image()方法也是可以
  • 同理传入的base64也需要这么做。
  • 为什么使用img.onload?原因是我们需等待图片加载完成再去进行操作,且图片加载的方法最好嵌套写,等图片1加载完加载图片2
  • 最后传入回调将获取的最后的base 以src的方式渲染到html中
creatEwm(this.convertCanvasToImage, document.getElementById('myCanvas'), function (dataUrl) {
   document.getElementById("canvasImg").src = dataUrl
})
复制代码

总结

以上就完成了前端去生成二维码,且封装后,在页面中写入的代码很少,就可以实现不同的二维码带不同的信息,且可以调起长按下载图片。

猜你喜欢

转载自juejin.im/post/5b4f03bee51d45194b18eb81