需求背景
微信小程序只提供分享到微信好友的接口,但是没有分享到朋友圈的接口。产品希望能生成一张带有小程序二维码的海报,让用户保存至本地,然后发往朋友圈,来实现分享到朋友圈的操作。
整理需求
- 准备一张海报
- 准备一张动态的小程序码,码上携带分享者信息
- 使用canvas把海报和小程序码拼成一张图片
- 保存canvas拼成的图片到本地
准备一张海报
海报图片需要先用过getImageInfo方法获取对应的filepath,才可以使用drawImage绘制。
注意:网络图片需先配置download域名才能生效,或者直接使用云存储,可以省略配置download域名这一步。
getImageInfo(src) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src,
success(res) {
resolve(res)
},
fail(err) {
reject(err)
},
})
})
}
准备一张动态的小程序二维码,码上携带分享者信息
小程序码有两个接口可以生成:get、getUnlimited。
get、getUnlimited差别主要是入参和生成数量,入参差别不是最重要的,我们的活动参加人数无法预估,所以一定要采用没有数量限制的getUnlimited接口。
getUnlimited接口调用方式有两种:HTTPS调用、云调用。
这个项目使用云调用(需要开通云开发服务)。
在cloudfunctions中先写一个生成小程序码的云函数工具,命名为miniprogramCode。
// miniprogramCode
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
try {
const page = event.page
const scene = `userid=${event.userid}`
const result = await cloud.openapi.wxacode.getUnlimited({ scene, page })
return result
} catch (err) {
return err
}
}
因为需要加载wx-server-sdk,所以需要安装一下依赖
npm install --save wx-server-sdk@latest
在miniprogram中写一个调用miniprogramCode工具的方法getMiniprogramCode备用
getMiniprogramCode () {
wx.cloud.init()
const userid = '用户的userid'
const page = 'pages/index/index'
return wx.cloud.callFunction({
name: 'qrcode',
data: { userid, page }
})
}
tips:miniprogramCode返回的小程序码的数据类型是Buffer类型,所以我们把他转化成本地路径才可以使用drawImage绘制。
先说说这个地方的知识点,平时用的不是很多。
- 本地用户文件是从 1.7.0 版本开始新增的概念。我们提供了一个用户文件目录给开发者,开发者对这个目录有完全自由的读写权限。通过 wx.env.USER_DATA_PATH 可以获取到这个目录的路径。
- wx.getFileSystemManager() 获取全局唯一的文件管理器
- FileSystemManager.writeFile(Object object) 写文件
getMiniprogramCodePath (buffer) {
const filePath = `${wx.env.USER_DATA_PATH}/miniprogram_code.jpeg`
const fs = wx.getFileSystemManager()
fs.writeFileSync(filePath, buffer, 'binary')
return filePath
}
使用canvas把海报和小程序码拼成一张图片
使用canvas,需要现在wxml文件中码好一个canvas组件
<canvas style="width: 250px; height: 406px" canvas-id="posterCanvas" />
data中数据准备好
data: {
posterImage: 'https://6465-dev-ecej-1300456941.tcb.qcloud.la/test.jpg',
}
然后开始画图
createCanvas () {
Promise.all([this.getImageInfo(this.data.posterImage), this.getMiniprogramCode()]).then(res => {
const imagePath = res[0].path
const miniprogramCode = res[1].result.buffer
const context = wx.createCanvasContext('posterCanvas')
context.drawImage(imagePath, 0, 0, 250, 406)
context.drawImage(this.getMiniprogramCodePath(miniprogramCode), 85, 300, 80, 80)
context.draw()
})
}
到这里,绘图工作就告一段落了。剩下的就是宝保存到本地。
保存canvas拼成的图片到本地
tips:以为保存很简单,并没有,细节多的很~~
- 通过wx.getSetting检测用户是否做过保存到相册的授权
- 如果没有,使用wx.authorize授权保存到相册
- canvas绘制得图片缓存到本地生成filepath
- 授权成功后,使用wx.saveImageToPhotosAlbum保存图片到系统相册就可以了
通过wx.getSetting检测用户是否做过保存到相册的授权
isWritePhotosAlbum() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: res => {
resolve(res.authSetting['scope.writePhotosAlbum'])
},
fail: res => {
reject()
}
})
})
}
如果没有,使用wx.authorize授权保存到相册
authWritePhotosAlbum () {
return new Promise((resolve, reject) => {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
resolve()
},
fail(err) {
reject(err)
}
})
})
}
canvas绘制得图片缓存到本地生成filepath
canvasToTempFilePath() {
return new Promise((resolve, reject) => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 250,
height: 406,
canvasId: 'posterCanvas',
fileType: 'jpg',
quality: 1,
success: res => {
resolve(res.tempFilePath)
},
fail: err => {
reject(err)
}
})
})
}
授权成功后,使用wx.saveImageToPhotosAlbum保存图片到系统相册就可以了
saveImageToPhotosAlbum (path) {
return new Promise((resolve, reject) => {
wx.saveImageToPhotosAlbum({
filePath: path,
success: res => {
resolve()
},
fail: err => {
reject()
}
})
})
}
最后把保存canvas拼成的图片到本地的流程串起来
async saveImage () {
try {
const isWritePhotosAlbum = await this.isWritePhotosAlbum()
if (!isWritePhotosAlbum) {
await this.authWritePhotosAlbum()
}
const filepath = await this.canvasToTempFilePath()
await this.saveImageToPhotosAlbum(filepath)
wx.showToast({
title: '保存成功',
})
} catch {
wx.showToast({
title: '保存失败',
})
}
}
END
朋友圈,走起。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。