页面基础分享能力

基本的页面分享,只需要在页面中设置 onShareAppMessage 即可,如果分享的内容各个页面保持一致,建议进行一定的封装,如封装到 Page 的能力中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
App({
// 获取分享卡片内容
getShareMessage(path) {
return {
title: '分享标题',
imageUrl: '分享图片',
path: path || '分享默认路径'
};
},
enhancePage() {
const oPage = Page;
Page = config => oPage(Object.assign(config, {
getShareMessage: this.getShareMessage,
}));
},
onLaunch() {
this.enhancePage();
},

})
1
2
3
4
5
Page({
onShareAppMessage() {
return this.getShareMessage(1);
}
})

用户点击按钮主动触发分享

只需要设置按钮的 open-typeshare 就可以自动触发页面的 onShareAppMessage 了。

1
<button open-type="share">分享按钮</button>

获取群聊中的分享信息

限于隐私保护,个人分享的信息已经不再能拿到了,但是我们可以获取分享所在群的信息。

  • 1.需要在分享页设置 ticket 信息
1
2
3
4
onLoad() {
// 配置分享,用以区分分享到个人还是群
wx.showShareMenu({withShareTicket: true});
}
  • 2.在 onShareAppMessage 里获取群信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
onShareAppMessage() {
return {
title: '分享',
path: '/pages/index',
success: (res) => {
const tickets = res.shareTickets;
if (res.shareTickets) {
wx.getShareInfo({
shareTicket: tickets[0],
success: (data) => {
console.log('分享到群: ', data);
},
});
} else {
console.log('分享到个人');
}
},
};
}
  • 3.在 APP.onLaunch 或者 App.onShow 里获取群信息
1
2
3
4
5
6
7
8
9
10
App({
onShow: (options) => {
wx.getShareInfo({
shareTicket: options.shareTicket,
success: (res) => {
// 请求微信服务器获取群信息
}
})
}
})

分享到朋友圈

小程序是不支持直接分享到朋友圈的,只能通过保存图片并引导用户主动发送朋友圈。下面的例子是一个分享动态生成的图片。

  1. 第一步:素材预下载,素材不支持远程URL,需要下载到本地(如小程序二维码和书封)
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
// 获取小程序二维码
downloadAppCode() {
return new Promise((resolve, rej) => {
wx.downloadFile({
url: '后台获取二维码接口',
success: (res) => { resolve(res.tempFilePath); },
fail: (res) => { resolve(''); }
});
});
},
// 下载文件
downloadFile(url) {
return new Promise((resolve, rej) => {
if (url){
wx.downloadFile({
url: url,
success: (res) => { resolve(res.tempFilePath); },
});
} else resolve();
});
},

// 下载所有书封到本地
downloadCovers(books) {
const urls = books.map((book) => this.getBookCover(book.bookId));
Promise.all([
this.downloadFile(urls[0]),
this.downloadFile(urls[1]),
this.downloadFile(urls[2]),
this.downloadFile(urls[3]),
this.downloadFile(urls[4]),
this.downloadAppCode(),
]).then((res) => {
const appCode = res[res.length - 1]; // 获取小程序二维码地址
res = res.splice(0, res.length - 1); // 所有书封地址
res = res.filter(item => item); // 过滤空书封
this.setData({ localCovers: res, appCode });
this.drawShareImg();
});
}
  1. 第二步:通过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
// 绘制分享图片
drawShareImg() {
const ctx = wx.createCanvasContext('shareImg');
const covers = this.data.localCovers;

// 背景
ctx.save()
ctx.setFillStyle('white')
ctx.fillRect(0, 0, 260, 370);
ctx.restore()

// nickname
ctx.setFillStyle('#111111');
ctx.setFontSize(14);
ctx.setTextAlign('center');
ctx.fillText(this.data.userInfo.nickName, 130, 42, 260);

// 文案 心愿书屋
// ctx.drawImage('../assets/images/share/share_icon_xysw.svg', 70, 52, 120, 30);
ctx.setFillStyle('#111111');
ctx.setTextAlign('center');
ctx.font = "30px SourceHanSerifCNMedium";
ctx.fillText('心愿书屋', 130, 82, 260);

// 书封边框
ctx.setStrokeStyle('rgba(0,0,0,0.1)');
if(covers[3]) ctx.strokeRect(21, 150, 42, 56);
if(covers[4]) ctx.strokeRect(197, 150, 42, 56);
if(covers[1]) ctx.strokeRect(51, 126, 60, 80);
if(covers[2]) ctx.strokeRect(149, 126, 60, 80);
if(covers[0]) ctx.strokeRect(91, 102, 78, 104);

// 书封
if(covers[3]) ctx.drawImage(covers[3], 21, 150, 42, 56);
if(covers[4]) ctx.drawImage(covers[4], 197, 150, 42, 56);
if(covers[1]) ctx.drawImage(covers[1], 51, 126, 60, 80);
if(covers[2]) ctx.drawImage(covers[2], 149, 126, 60, 80);
if(covers[0]) ctx.drawImage(covers[0], 91, 102, 78, 104);

// 矩形背景
ctx.rect(0, 226, 260, 66);
ctx.setFillStyle('#FFDCE7');
ctx.fill();

// 引号
ctx.drawImage('/assets/images/share/share_icon_left.png', 20, 242, 20, 12);
ctx.drawImage('/assets/images/share/share_icon_right.png', 220, 264, 20, 12);

// 二维码
ctx.drawImage(this.data.appCode, 108, 309, 44, 44);

// 文案 我已经领了129书币
ctx.setFillStyle('#773A4D');
ctx.font = "14px SourceHanSerifCNMedium";
ctx.setTextAlign('center');
ctx.fillText('我已经领了129书币', 130, 254, 260);

// 文案 天天领币,免费看书
ctx.setFillStyle('#773A4D');
ctx.font = "14px SourceHanSerifCNMedium";
ctx.setTextAlign('center');
ctx.fillText('天天领币,免费看书', 130, 274, 260);

// 文案 识别小程序码
ctx.setFillStyle('#9B9B9B');
ctx.setFontSize(12);
ctx.setTextAlign('left');
ctx.fillText('识别小程序码', 30, 337, 260);

// 文案 进入心愿书屋
ctx.setFillStyle('#9B9B9B');
ctx.font = "12px SourceHanSerifCNMedium";
ctx.setTextAlign('left');
ctx.fillText('进入心愿书屋', 158, 337, 260);

ctx.draw();
},
  1. 第三步:通过微信api下载图片到手机相册
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
canvasToFile() {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 260, // 画布区域宽度
height: 370, // 画布区域高度
destWidth: 260 * 4, // 保存图片宽度
destHeight: 370 * 4, // 保存图片高度
canvasId: 'shareImg',
success: (res) => {
this.saveImage(res.tempFilePath);
},
fail: function (err) {
console.log('生成图片失败');
},
});
},
// 保存图片
saveImage(filePath) {
wx.saveImageToPhotosAlbum({
filePath:filePath,
success: (res) => {
this.showSuccess('图片保存成功');
},
fail: () => {
this.showError('图片保存到相册失败', '图片无法保存到相册,请稍后重试');
},
});
},
  • 本地图片处理注意事项 模拟器上都是骗人的
1
2
3
4
1. 不要使用相对路径,只能使用绝对路径
2. 图片不支持svg不支持svg不支持svg
3. 图片不支持base64,只支持本地图片和网络图片两种
* 如果使用了相对路径、svg、base64,模拟器上运行顺畅的毫无破绽,但是在真机上是绘制不出来的!!!
1
2
还是老老实实转化成网络图片再下载吧!!!
相关问题:https://developers.weixin.qq.com/community/develop/doc/00048c046f0028e62247f403651800?highLine=drawimage%2520base64
  • 模拟器坑爹二连
1
2
明明在模拟器上特殊字体是有效的,为什么到了真机上就又变成了默认字体了???
想要用字体?那就让设计切个图片给你吧

分享参数问题:新用户扫描后处理scene值

生成二维码时会带上scene值,当其他人扫描后可以从scene值中解析出有用的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
decodeURLParams(str) {
const result = {}
const params = str.split('&');
for (let param of params) {
const keyValue = param.split('=');
result[keyValue[0]] = keyValue[1];
}
return result;
},
onLoad() {
let bookId = '';
if (options.bookId) bookId = options.bookId;
else if (options.scene) bookId = this.decodeURLParams(decodeURIComponent(options.scene)).bookId || '';
this.setData({ bookId: bookId });
}