小程序学习:前端渲染二维码分享海报

需求原因

由于小程序本身环境的限制,不提供朋友圈分享的相关API,因此小程序开发者无法方便直接的将小程序分享到朋友圈。因此为了解决这一需求,常用的解决方法是生成带有“小程序码”的海报图片,用户将该图片分享至朋友圈。通过扫描图片上的小程序码进入小程序来间接解决这一问题。

微信小程序码API简介和选择

微信提供了三种生成小程序码的接口,均需要在服务端(后端)进行调用,无法在前端调用。

  • 接口 A: 适用于需要的码数量较少的业务场景。
    生成小程序码,可接受 path 参数较长,生成个数受限。
  • 接口 B:适用于需要的码数量极多的业务场景。
    生成小程序码,可接受页面参数较短,生成个数不受限。
  • 接口 C:适用于需要的码数量较少的业务场景。
    生成二维码,可接受 path 参数较长,生成个数受限

其中接口C生成的是二维码而不是小程序码,因此不推荐使用。

接口A和接口C具体的数量限制为:接口 A 加上接口 C,总共生成的码数量限制为 100,000。

因此根据业务需求我选择的是接口B。不过估计使用该功能的用户基本上应该都是使用的这个接口,因为该接口适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。

接口B相比于接口A,劣势在于可以接受的页面参数较短,在32个字符以内,但这个参数长度对于大多数业务来说其实都够用了;

而另外一个劣势则在于存在调用频率限制,调用分钟频率受限5000次/分钟。这个劣势则可以通过后端预生成的方式来解决。

小程序码的生成和使用

通常小程序在实现分享海报这一功能时,会采用后端直接生成好海报图片并将其的url地址传给前端,前端直接使用即可。

但我的需求则并存在一些不一样的地方:1. 该需求目前只有部分功能需要使用,后端来生成海报、保存海报的必要性不大,且该功能的成本较高。等到确定所有功能均确定使用该功能时再通过后端生成图片即可;2. 是否需要海报功能还不确定,需要通过数据验证,前端进行实验更方便,无需占用后端资源。

因此,整个海报功能后端的唯一作用是拿到前端传过来的参数并调用微信api,将微信的返回值再转给前端。相当于一个中间件的作用。

请求小程序码

后端通过调用下面的微信api生成,然后将返回值直接转给前端即可。

POST https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN

请求参数

pic1.png

参数需要注意的是scene的值受长度限制,因此如何将一个非常长的参数串精简到32位以内是重点。

我采用的方法是,先去除所有不必要的参数,只留必要的参数。参数名省略到一位(最好写一个备注)。参数属性值如果为数字,则全部转换为36进制,有需要可以转换到更高。

而在进行接口对接时我这里还出现了一个问题,就是明明字符数少于32位的scene值,调用接口后却返回参数过长的报错。

所传字符:

pic2.png

返回值:

pic4.png

而且神奇的是这个报错时有时无,具体原因还没有查到(目测微信锅)不过在将“=”和“&”两个字符转换为普通大写英文字符就稳定不报错了,因此以防万一,我将“=”和“&”等特殊字符均用大写字母来代替。

网上通常采用的方法是后端将整个参数存在数据库内,将其标识当作参数传给微信,前端扫码后获得这个标识,再调用后端接口从数据库拿出完整参数。如果参数实在过长无法省略,这也是方法之一。

返回值

返回值说明:如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON 格式的数据。

pic5.png

返回失败的不做过多说明,JSON数据正常处理即可。这里的重点是如何解决成功调用接口时返回的图片二进制内容。返回内容在开发者工具里看起来就是这样的一串乱码

pic6.png

微信无法直接解析该数据,但小程序有arrayBufferToBase64方法,可以解析arraybuffer数据,因此我们可以先拿到arrayBuffer数据类型的图片文件

在二维码请求接口调用时,wx.request的responseType的值设为arraybuffer

pic7.png

此时返回的内容被转换为arrayBuffer数据,再使用arrayBufferToBase64

何为arrayBuffer

dispatch(acFetchQrCode({ // 接口请求
  scene: paramString
})).then(res => { 返回值
  console.log(res); 打印arrayBuffer返回值
  const base64 = wx.arrayBufferToBase64(res);
  console.log(base64); 打印base64数据
}

pic8.png

可以看到arrayBuffer数据和base64数据已经被打印出来了,得到base64后处理就方便了:

const imgPath = `${wx.env.USER_DATA_PATH}/ererwei.png`; // 设定图片保存临时路径
const imageData = base64.replace(/^data:image\/\w+;base64,/, ''); // 表示为基于base64编码的图片文件
console.log(imageData);
const fs = wx.getFileSystemManager();
fs.writeFile({
  filePath: imgPath,
  data: imageData,
  encoding: 'base64',
  success: () => {
    this.qrPath = imgPath; // 之后就可以直接用qrPath来使用二维码图片了
    this.loadDefaultImage(albumPosterData); // 进行后续其他操作,这里是下载其他要使用的图片
  }
});

将该base64数据表示为基于base64编码的图片文件,这个知识点是Data URI scheme

最后使用wx.getFileSystemManager().writeFile将其写为本地的文件即可进行使用。

进行海报的绘制

最后一步就是进行海报的绘制,这里需要使用到小程序的canvas组件,将不同的图片和文字组合后绘制出完整海报,再将其保存为图片存在用户相册中。这里有两个重点:

网络图片在canvas上的绘制

微信canvas组件中,绘制图片的drawImage方法无法直接使用图片的url链接来进行绘制,只能将本地图片绘制到canvas中。

因此,如果需要绘制网络图片,需要先将图片下载至本地,再调用该图片的本地路径来进行绘制:

pic9.png

调用后会得到图片的本地路径,再绘制即可

生成后的海报在小程序中的展现

由于在微信小程序内,canvas是原生组件,微信的原生组件收到非常多的限制。因此如果要将生成的海报在小程序中进行展现,直接用canvas是非常不方便的。因此建议将canvas隐藏,只负责生成海报,图片用image组件来展示。

绘制后的效果如下:

pic10.png

总结

小程序前端渲染二维码分享海报让自己收获了很多,包括canvas能力、如何去实现不了解的新功能的能力。在实现该功能时自己也遇见了很多知识盲区,比如Data URI scheme、ArrayBuffer等知识点都是自己以前没有涉及到的。之后针对这两点会再写出两篇学习笔记,flag已立!

 linux服务器配置前端环境相关知识点
骨架屏的原理和使用 
上一篇:linux服务器配置前端环境相关知识点
下一篇:骨架屏的原理和使用


如果我的文章对你有帮助,或许可以打赏一下呀!

支付宝
微信
QQ