小程序云开发生成二维码并保存到文件
发布于 4 年前 作者 xiulanjiang 4592 次浏览 来自 分享

小程序云开发

云开发已经出来很久的时间了,但是一直没有使用,原因是一些基本框架都还在原来的服务。这次想参考礼物小盲盒做一个小程序。内容比较简单,刚好适合拿来做云开发练手,就从此开启云开发之路。

云开发整体使用还是比较方便的,这里不作过多的介绍,重点说下今天开发遇到的第一个小小的环节,生成一张二维码分享图可以保存分享到朋友圈。

页面效果

实现方法

先来看看官方提供的文档:云开发获取小程序码

接口方法:openapi.wxacode.getUnlimited
需在 config.json 中配置 wxacode.getUnlimited API 的权限

属性 类型 默认值 必填 说明
scene string 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&’()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
page string 主页 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面

1. 在 config.json 中配置 wxacode.getUnlimited API 的权限

在你云函数下的config.json文件中,增加以下代码:

{
  "permissions": {
    "openapi": [
      "wxacode.getUnlimited"
    ]
  }
}

2. scene只支持32个可见字符

如果你的参数过长,则需要将参数进行缩短,可以通过短码,短参数名的方式。我这里只需要一个boxId,刚好32位,这里直接使用boxId。

3. 云端生成二维码并保存

分享图除了二维码,还需要一些其他信息,这些信息是通过本地使用canvas进行绘制,而二维码需要从服务端生成。因为需要请求云函数,获取生成的二维码链接。

由于wxacode.getUnlimited返回结果图片buffer,这里使用云文件管理的方法,将获取到的buffer 写入本地文件,然后返回云文件ID给小程序端。

来看代码:

async function getQrCode(scene, page, fileName) {
    try {
        var fileName = 'qrcode/' + fileName + '.png';
        const result = await cloud.openapi.wxacode.getUnlimited({
            scene: scene,
            page: page
        })
        if (result && result.buffer) {
            var res = await cloud.uploadFile({
                cloudPath: fileName,
                fileContent: result.buffer,
            })
            if (res.fileID) {
                return res.fileID
            }
        }
        return false
    } catch (err) {
        console.error(err)
        return false
    }
}

这里没有对二维码是否已经存在做检查,每次调用都会重新生成。因此在外部调用的地方需要检查是否已经生成,提高性能。

云开发文件存储相关API :https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/storage/api.html

将fileID 直接返回给小程序端,即可展示二维码。
但是这里还需要在小程序端画出分享图

4. 生成分享图

这里使用canvas绘制图片,但是canvas绘制图片需要为本地图片,先通过
wx.getImageInfo获取本地临时File地址。

    loading: function (qrcode, avatarUrl, qrBackground) {
    	var _this = this;
        var a = new Promise(function (r, j) {
            wx.getImageInfo({
                src: qrcode,
                success: function (t) {
                    r(t);
                }
            });
        }), b = new Promise(function (r, j) {
            wx.getImageInfo({
                src: avatarUrl,
                success: function (t) {
                    r(t);
                }
            });
        }), c = new Promise(function (r, j) {
            wx.getImageInfo({
                src: qrBackground,
                success: function (n) {
                    r(n);
                }
            });
        });
        Promise.all([a, b, c]).then(function (t) {
            _this.createNewImg(t[0].path, t[1].path, t[2].path);
        });
    },
   
    createNewImg: function (qrcode, avatarUrl, qrBackground) {
        var _this = this, config = _this.data.config, canvas = wx.createCanvasContext("myCanvas");
        canvas.drawImage(qrcode, 260, 393, 150, 150),
        canvas.drawImage(qrBackground, 0, 0, 670, 670),
        canvas.font = "normal bold 28px simhei",
        canvas.fillStyle = "#000000";
        var s = 335 - canvas.measureText("礼物份数:" + _this.data.num + "份").width / 2;
        canvas.fillText("礼物份数:" + _this.data.num + "份", s, 173), canvas.font = "normal bold 50px simhei",
        canvas.fillStyle = "#000000";
        var qrTxt = config.giftConfig.qrTxt;
        if (qrTxt.length > 10) {
            var u = 335 - canvas.measureText(qrTxt.substr(0, 10)).width / 2, r = 335 - canvas.measureText(qrTxt.substr(10, 100)).width / 2;
            canvas.fillText(qrTxt.substr(0, 10), u, 250), canvas.fillText(qrTxt.substr(10, 100), r, 325);
        } else {
            var f = 335 - canvas.measureText(qrTxt).width / 2;
            canvas.fillText(qrTxt, f, 250);
        }
        canvas.arc(335, 468, 35, 0, 2 * Math.PI, !0), 
        canvas.clip(), 
        canvas.drawImage(avatarUrl, 300, 433, 70, 70),
        canvas.stroke(), 
        canvas.draw(), 
        setTimeout(function () {
            wx.canvasToTempFilePath({
	            canvasId: "myCanvas",
	            success: function (n) {
	                var e = n.tempFilePath;
	                wx.hideLoading(), 
	                _this.setData({
	                    url: e
	                });
	            },
	            fail: function (t) { }
        });
        }, 500);
    },

再通过wx.canvasToTempFilePath函数将canvas 保存为本地临时文件,将url设置并展示即可。

wxml代码示例:

<image id="wenan" mode="widthFix" src="{{url}}"></image>
<canvas canvasId="myCanvas" style="width:670px;height:670px;margin-top:1000px;position:fixed"></canvas>

还有保存按钮申请存储权限这里就不说了,属于小程序基本操作。

回到顶部