业务需求
开发过程中经常会遇到这样的需求,把指定的页面分享到朋友圈。这在H5页面是没有问题的,直接调用JSSDK的分享接口即可,但是小程序是无法直接分享到朋友圈的,所以我们只能通过分享一个小程序的二维码出去,其他人通过扫码进入指定页面。
节假日大家都会用携~旅行的等软件进行抢票,分享到朋友圈让好友帮忙加速,这里就是通过分享一个二维码,好友扫码进入小程序进行加速。查了一下发现确实有不少做过该功能的大佬。这里我也在实现并验证没问题之后做一个总结。
实现步骤
-
前端通过调用服务端的接口,把生成小程序二维码需要的参数传递过去。然后服务端去调小程序的接口获取二维码(因为前端无法直接调用该接口)。
-
前端把服务端返回的图片下载下来。
-
通过调用canvas的api把二维码图片和想要添加的元素绘制到画布上。(前面图片没有下载的话是画不上去的)
-
绘制完成之后,调用相关接口把画布专程图片
-
把转换成的图片保存到本地,然后就可以去朋友圈手动分享了。
代码实现
请求获取二维码接口,需要传递两个必须的参数:
-
page:要分享的小程序页面(必须是已经发布,否则报错),后面不能带参数
-
scene:这个字段才是传递页面所需参数的字段。需要注意该字段最多为32个字符,多参数的话可以用&分开,总之和解析的代码对应就可以。
获取到二维码路径,通过wx.downloadFile()
API将图片下载到本地,然后就可以操作canvas了,根据自己的业务需求进行绘制。
-
canvas标签要有一个canvas-id以便在js中通过这个id获取画布。
-
创建一个画布对象
createCanvasContext(canvas-id)
,传入画布的id。 -
进行一系列绘制操作,具体可以查看对应的API。这里我只是简单的把二维码画上去,然后加了一行字。
需要注意的是,生成的图片背景是黑色,所以我最先画了一个和画布大小一样的白色矩形作为背景。
<canvas style="width: 100vw; height: 500px" canvas-id="shareImg"></canvas>
getImage() {
util
.request(
`${api.ApiRootUrl}/wechat/codeUnlimit`,
{
scene: `${this.data.articleId}&${this.data.type}`,
page: 'pages/detail/detail'
},
'POST'
)
.then(response => {
wx.downloadFile({
url: `${response.image}`,
success: res => {
const ctx = wx.createCanvasContext('shareImg');
//绘制一个白色矩形,宽度为屏幕宽度
ctx.setFillStyle('#fff');
ctx.fillRect(0, 0, this.data.windowWidth, 500);
// 把二维码画上去
ctx.drawImage(
res.tempFilePath,
this.data.windowWidth / 2 - 75,
30,
150,
150
);
// 绘制想要的文字
ctx.setTextAlign('center');
ctx.setFontSize(24);
ctx.setFillStyle('red');
ctx.fillText('请手动分享到朋友圈', this.data.windowWidth / 2, 220);
ctx.stroke();
// 画(前面都是准备,这才是画的那一步)
ctx.draw();
this.canvasToImage();
},
fail() {
wx.showToast({
title: '获取二维码失败',
duration: 2000
});
}
});
});
},
上面已经把想要的内容都画出来了,接着就是把画布转成图片。这里调用canvasToTempFilePath
API,然后设置一些参数(画布的宽高、输出图片的宽高、类型等等),具体看文档。
这里需要注意的是要加一个延时操作,否则图片出不来的。
canvasToImage() {
setTimeout(() => {
wx.canvasToTempFilePath({
canvasId: 'shareImg',
width: 400,
height: 500,
destWidth: 400,
destHeight: 500,
fileType: 'jpg',
success: res => {
wx.showToast({
title: '图片已生成',
icon: 'success',
duration: 2000
});
this.setData({
resultImage: res.tempFilePath
});
},
fail: () => {
wx.showToast({
title: '图片生成失败',
icon: 'success',
duration: 2000
});
}
});
}, 0);
},
最后就是保存图片到本地了,使用wx.saveImageToPhotosAlbum()
API,将刚才转成图片获取到的路径传入。到此生成二维码并保存到本地就完成了。
saveImageToLocal() {
wx.saveImageToPhotosAlbum({
filePath: this.data.resultImage,
success: res => {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
});
},
fail() {
wx.showToast({
title: '保存失败',
duration: 2000
});
}
});
}
但是,记得修改该页面对传入参数的操作。如果是通过扫码进来的,获取参数的方式是不一样的,所以要做处理。之前正常进入该页面直接从option中获取对应参数。这里改为判断option.scene字段存不存来区分是否是扫码进来的。
如果是扫码进来的,就根据之前你传给服务端scene字段时的格式去解析参数,在进行赋值。这里通过&来分割参数再分别获取。
onLoad: function(option) {
let articleId, type;
if (option.scene) {
let scene = decodeURIComponent(option.scene);
articleId = scene.split('&')[0];
type = scene.split('&')[1];
} else {
articleId = option.id;
type = option.type;
}
}
网友评论