微信小程序使用前端实现动态二维码海报分享(涉及云函数)

null

最近给自己的拼团小程序添加一个海报分享的功能,由于要分享特定的商品,需要动态路由的二维码,这样的话,就没办法直接内置一个二维码了,只能向后端请求,然后保存到本地。但是不想动后端的接口了,就想到了只用前端生成:

下面是实现流程思路:

1.向后端请求指定商品id路由的参数,后端返回该页面的二维码海报:放弃!
2.使用云函数获取小程序二维码,支持路由参数,保存到小程序本地,通过canvas绘制,生成海报:Bingo!

然后就是编码的问题:

1.云函数的使用
2.canvas绘制网络图片(需要先使用wx.getImageInfo拿到临时路径)
3.动态设置海报的尺寸
4.定制其它内容(头像,文本)

效果图:

1.gif

在这个过程中:点击分享按钮,把canvas的hidden关闭(canvas层级太高),开始绘制封面图(网络路径),请求小程序码,绘制小程序码,绘制文本,由于有时候延迟很大,所以去除了头像绘制,代码会给出示例。

开始代码

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//绘制海报

renderShare() {

let that = this;

//绘制背景

ctx.save();

ctx.fillStyle = "#FFFFFF";

ctx.fillRect(0, 0, this.data.windowWidth * .8, this.data.windowWidth * .8 + 120);

ctx.draw()

ctx.restore();

ctx.setFontSize(18)

ctx.fillStyle = "#000000";

ctx.fillText(`一起来扫码领【${this.data.goods_info.coupon_discount / 100}元券】`, 90, this.data.windowWidth * .8 + 75)

ctx.draw(true)

ctx.save()



//console.log(e);

// let avatarurl_width = 60,

// avatarurl_heigth = 60,

// avatarurl_x = 30, //绘制的头像在画布上的位置

// avatarurl_y = 30; //绘制的头像在画布上的位置



// ctx.beginPath();

//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针

//ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);

// ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸

console.log('开始绘制')

// ctx.drawImage(e.path, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片

wx.getImageInfo({

src: that.data.goods_info.goods_gallery_urls[0],

success(ee) {

console.log(ee)

ctx.restore()

//计算海报宽度

let paperW = that.data.windowWidth * .8;

//计算图片居中

ctx.drawImage(ee.path, 0, 0, paperW, paperW)

ctx.draw(true)

console.log(ctx);

//获取小程序码

const res = wx.cloud.callFunction({

// 要调用的云函数名称

name: 'getCodeImg',

data: {

goods_id: that.data.goods_info.goods_id

}

});

res.then((code) => {

console.log(code)

console.log(code_filePath)

fsm.writeFile({

filePath: code_filePath,

data: code.result.buffer,

encoding: 'binary',

success() {

console.log(code_filePath)

console.log(code_filePath)

wx.getImageInfo({

src: code_filePath,

success(code_result) {

console.log(code_result)

ctx.drawImage(code_result.path, 30, that.data.windowWidth * .8 + 40, 52.2, 59.4)

ctx.draw(true)

//canvas生成图片

wx.canvasToTempFilePath({

canvasId: 'shareImg',

success(canvas_img) {

canvas_imgPath = canvas_img.tempFilePath;



},

fail(canvas_fail) {

console.log(canvas_fail)

},

complete(e){

wx.hideToast(tips)

}

}, this)

}

})

},

fail() {



},

});



});

}

})




},

这里注意几个地方:canvas绘制网络图一定要先用wx的API转换成临时文件再绘制。

没有使用过云函数的小伙伴看这里:微信官方为我们提供了云函数的便利,我们需要在本地建立一个云函数的目录,开发工具会自动识别,比如我这里建立了cloudfunctions后面的| shell-goods是工具自动添加的!

在里面我们可以建立云函数目录,比如这个getCodeImg

一个函数是一个目录哦,打开只有config.js和index.js 下面就是index.js的内容,具体请移步微信文档:云开发

捕2获.PNG

一个小提示:关于引入

const cloud = require('wx-server-sdk')

需要使用NPM安装哦

然后最后一步就是不要忘记,右键云函目录,点击部署!!!

之后在其它页面我们就可以使用下面的方式调用了,参数也是可以传的。

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
// 云函数入口文件

const cloud = require('wx-server-sdk')



cloud.init()



// 获取小程序码

exports.main = async(event, context) => {

let result = await cloud.openapi.wxacode.createQRCode({

path: 'pages/shop/goods/goods?goods_id=' + event.goods_id,

//是否透明底图

is_hyaline: true,

width: 300

});

console.log(result)

return result

}

其实如果可以,还是尽量从后端生成比较好,快速,尤其是想绘制背景的时候,前端本地每次都要将网络转为临时文件再绘制到canvas太慢了。

onLoad拿到入口参数

1
2
3
4
5
6
7
8
9
if  (lauchInfo.query.goods_id !=  undefined  && lauchInfo.query.goods_id.goods_id !=  ""){

mThis.initData(lauchInfo.query.goods_id);

console.log("sc")

return false

}