微信小程序利用canvas生成海报分享图片

一 . 效果

今天给大家介绍一下,小程序如何生成二维码分享海报,大家都知道小程序目前没办法分享到朋友圈中,这边我们可以利用海报的方式,来进行朋友圈分享。

image

二 . 准备

准备两张图片连接,最好是自己开发账号验证的https图片链接。

三 . 实现思路

其实就是canvas实现方式,首先要就是定义一个canvas容器,把容器放在中间,图片也要动态计算大小居中,显示下面的文字和二维码也是要根据容器动态去改变,这就是大概的实现思路。

四 . 实现代码

利用微信小程序canvas生成海报分享图片,这个生成图片排版和适配不同尺寸的手机是一个难点,特别是图片适应问题,我处理的方法是动态获取容器的宽度进行适应就是利用微信API wx.createSelectorQuery(),不知道还有没有更好的办法可以请教。

1.下载头像

为了确保图片下载完成之后,再回调其它方法执行下一步。

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
getAvaterInfo: function (cardInfo) {//cardInfo是传入的信息参数,按实际需要。
wx.showLoading({ title: '生成中...',mask: true,});
var that = this;
if (cardInfo.CardInfo.Avater) {
wx.downloadFile({
url: '图片路径',
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var avaterSrc = res.tempFilePath;
that.getQrCode(avaterSrc, cardInfo);
}else{
wx.showToast({
title: '头像下载失败!',
icon:'none',
duration: 2000,
success:function(){
that.getQrCode(avaterSrc = "", cardInfo);//回调另一个图片下载
}
})
}
}
})
} else {
wx.hideLoading();
that.getQrCode(avaterSrc = "", cardInfo);//回调另一个图片下载
}
},

2.下载二维码

二维码下载一样的道理,就是先下载完成,再进行绘图。

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
getQrCode: function (avaterSrc, cardInfo) {
wx.showLoading({ title: '生成中...', mask: true, });
var that = this;
if (cardInfo.CardInfo.QrCode) {
wx.downloadFile({
url: cardInfo.CardInfo.QrCode,
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var codeSrc = res.tempFilePath;
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
} else {
wx.showToast({
title: '二维码下载失败!',
icon: 'none',
duration: 2000,
success: function () {
var codeSrc = "";
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
}
})
}
}
})
} else {
wx.hideLoading();
var codeSrc = "";
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的绘图方法
}
},

3.绘制分享海报

这里才是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
sharePosteCanvas: function (cardInfo, avaterSrc, codeSrc) {
wx.showLoading({
title: '生成中...',
mask: true,
})
var that = this;
const ctx = wx.createCanvasContext('myCanvas');
var width = "";
wx.createSelectorQuery().select('#canvas-container').boundingClientRect(function (rect) {
var height = rect.height;
var right = rect.right;
width = rect.width * 0.8;
var left = rect.left + 5;
ctx.setFillStyle('#fff');
ctx.fillRect(0, 0, rect.width, height);

//头像
if (avaterSrc) {
ctx.drawImage(avaterSrc, left, 20, width, width);
ctx.setFontSize(14);
ctx.setFillStyle('#fff');
ctx.setTextAlign('left');
}

if (cardInfo.TagList.length > 0) {
ctx.fillText(cardInfo.TagList[0].TagName, left + 20, width - 4); //标签
const metrics = ctx.measureText(cardInfo.TagList[0].TagName); //测量文本信息
ctx.stroke();
ctx.rect(left + 10, width - 20, metrics.width + 40, 25);
ctx.setFillStyle('rgba(255,255,255,0.4)');
ctx.fill();
}

if (cardInfo.CardInfo.Name) {
ctx.setFontSize(14);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Name, left, width + 60); //姓名
}

if (cardInfo.CardInfo.Position) {
ctx.setFontSize(12);
ctx.setFillStyle('#666');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Position, left, width + 85); //职位
}

if (cardInfo.CardInfo.Mobile) {
ctx.setFontSize(12);
ctx.setFillStyle('#666');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Mobile, left, width + 105); //电话
}

if (cardInfo.CardInfo.Company) {
// 公司名称
const CONTENT_ROW_LENGTH = 24; // 正文 单行显示字符长度
let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.CardInfo.Company, CONTENT_ROW_LENGTH);
ctx.setTextAlign('left');
ctx.setFillStyle('#000');
ctx.setFontSize(10);
let contentHh = 22 * 1;
for (let m = 0; m < contentArray.length; m++) {
ctx.fillText(contentArray[m], left, width + 150 + contentHh * m);
}
}

// 绘制二维码cardInfo.CardInfo.QrCode
if (codeSrc) {
ctx.drawImage(codeSrc, left + 150, width + 40, width / 3, width / 3)
ctx.setFontSize(10);
ctx.setFillStyle('#000');
ctx.setTextAlign('right');
ctx.fillText("微信扫码或长按识别", left + 235, width + 150);
}

}).exec()

setTimeout(function () {
ctx.draw(); 这里有个需要注意就是,这个方法是在绘制完成之后在调用,不然容易其它被覆盖。
wx.hideLoading();
}, 1000)

},

4.多行显示文字

这个函数就是需要多行显示文字的时候进行折行,就是切分为数组。

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
textByteLength(text, num) { // text为传入的文本  num为单行显示的字节长度
let strLength = 0; // text byte length
let rows = 1;
let str = 0;
let arr = [];
for (let j = 0; j < text.length; j++) {
if (text.charCodeAt(j) > 255) {
strLength += 2;
if (strLength > rows * num) {
strLength++;
arr.push(text.slice(str, j));
str = j;
rows++;
}
} else {
strLength++;
if (strLength > rows * num) {
arr.push(text.slice(str, j));
str = j;
rows++;
}
}
}
arr.push(text.slice(str, text.length));
return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数]
},

5.保存绘制生成图片

这一步就是最后把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
//点击保存到相册
saveShareImg: function () {
var that = this;
wx.showLoading({
title: '正在保存',
mask: true,
})
setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function (res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showModal({
content: '图片已保存到相册,赶紧晒一下吧~',
showCancel: false,
confirmText: '好的',
confirmColor: '#333',
success: function (res) {
if (res.confirm) { }
},
fail: function (res) { }
})
},
fail: function (res) {
wx.showToast({
title: res.errMsg,
icon: 'none',
duration: 2000
})
}
})
}
});
}, 1000);
},

五 . 填坑

1.图片要提前下载

这里面还有一个问题就是,图片要提前下载完之后再绘图,不然图片显示不出来,可以把下载图片的方法单独拎出来,然后下载图片后回调绘图方法。

ctx.draw()

这个方法是在绘制完成之后在调用,不然容易其它被覆盖。

六、总结

今天的内容就介绍到这边,明天再给大家深入的介绍一下:如何来生成特定页面的小程序二维码海报。

林老师带你学编程 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!