由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~
这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能)
咱们不多说,直接上手就是干。
首先我们新增一个自定义组件,在该组件的json中引入painter
{
"component": true,
"usingComponents": {
"painter": "/painter/painter"
}
}
然后组件的WXML (代码片段在最后)
// 将该组件定位在屏幕之外,用户查看不到。
<painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" />
重点来了 JS (代码片段在最后)
Component({
properties: {
// 是否开始绘图
isCanDraw: {
type: Boolean,
value: false,
observer(newVal) {
newVal && this.handleStartDrawImg()
}
},
// 用户头像昵称信息
userInfo: {
type: Object,
value: {
avatarUrl: '',
nickName: ''
}
}
},
data: {
imgDraw: {}, // 绘制图片的大对象
sharePath: '' // 生成的分享图
},
methods: {
handleStartDrawImg() {
wx.showLoading({
title: '生成中'
})
this.setData({
imgDraw: {
width: '750rpx',
height: '1334rpx',
background: 'https://qiniu-image.qtshe.com/20190506share-bg.png',
views: [
{
type: 'image',
url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg',
css: {
top: '32rpx',
left: '30rpx',
right: '32rpx',
width: '688rpx',
height: '420rpx',
borderRadius: '16rpx'
},
},
{
type: 'image',
url: this.data.userInfo.avatarUrl || 'https://qiniu-image.qtshe.com/default-avatar20170707.png',
css: {
top: '404rpx',
left: '328rpx',
width: '96rpx',
height: '96rpx',
borderWidth: '6rpx',
borderColor: '#FFF',
borderRadius: '96rpx'
}
},
{
type: 'text',
text: this.data.userInfo.nickName || '青团子',
css: {
top: '532rpx',
fontSize: '28rpx',
left: '375rpx',
align: 'center',
color: '#3c3c3c'
}
},
{
type: 'text',
text: `邀请您参与助力活动`,
css: {
top: '576rpx',
left: '375rpx',
align: 'center',
fontSize: '28rpx',
color: '#3c3c3c'
}
},
{
type: 'text',
text: `宇宙最萌蓝牙耳机测评员`,
css: {
top: '644rpx',
left: '375rpx',
maxLines: 1,
align: 'center',
fontWeight: 'bold',
fontSize: '44rpx',
color: '#3c3c3c'
}
},
{
type: 'image',
url: 'https://qiniu-image.qtshe.com/20190605index.jpg',
css: {
top: '834rpx',
left: '470rpx',
width: '200rpx',
height: '200rpx'
}
}
]
}
})
},
onImgErr(e) {
wx.hideLoading()
wx.showToast({
title: '生成分享图失败,请刷新页面重试'
})
//通知外部绘制完成,重置isCanDraw为false
this.triggerEvent('initData')
},
onImgOK(e) {
wx.hideLoading()
// 展示分享图
wx.showShareImageMenu({
path: e.detail.path,
fail: err => {
console.log(err)
}
})
//通知外部绘制完成,重置isCanDraw为false
this.triggerEvent('initData')
}
}
})
那么我们该如何引用呢?
首先json里引用我们封装好的组件share-box
{
"usingComponents": {
"share-box": "/components/shareBox/index"
}
}
以下示例为获取用户头像昵称后再生成图。
<button class="intro" bindtap="getUserInfo">点我生成分享图</button>
<share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}" bind:initData="handleClose" />
调用的地方:
const app = getApp()
Page({
data: {
isCanDraw: false
},
// 组件内部关掉或者绘制完成需重置状态
handleClose() {
this.setData({
isCanDraw: !this.data.isCanDraw
})
},
getUserInfo(e) {
wx.getUserProfile({
desc: "获取您的头像昵称信息",
success: res => {
const { userInfo = {} } = res
this.setData({
userInfo,
isCanDraw: true // 开始绘制海报图
})
},
fail: err => {
console.log(err)
}
})
}
})
最后绘制分享图的自定义组件就完成啦~效果图如下:
tips:
- 文字居中实现可以看下代码片段
- 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号
代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5
您好,我能通过这个来实现 小程序特定页面(就小窗播放的视频view)画面的截取保存上传吗
你好,请问一定要下载到本地么?
我canvas转变成img,获取到了temFilePath的路径,我直接赋值给了onShareAppMessage的imageUrl,但是没有生效。
楼主 绘制图片是异步的 如果我拿图片做canvas的背景图 然后绘制文本 但是因为图片是异步绘制 就会 导致图片绘制的慢 最后遮盖住了文本 怎么解决呢
views: [ { type: 'image', url: wx.getStorageSync('imageUrl') || 'https://default-avatar.png', css: { top: '0rpx', left: '0rpx', right: '0rpx', width: '560rpx', height: '558rpx', borderRadius: '16rpx' }, }, ]
楼主,您好!上次绘制云存储的图片,通过您给的 wx.cloud.getTempFileURL({})这个函数实现了云存储ID,转换为图片的URL,可以实现图片绘制,谢谢!
这次我遇到了 绘制图片的时候,设置图片的宽和高的时候, 较小的那个数值不是按照设置的数值绘制的,比如本例中(width: '560rpx', height: '558rpx',) 宽是560rpx没问题,但是高只要设置小于宽的值都不会正确显示,我无论把高设置为 550rpx. 558rpx,绘制图片都一样,只有把高设置为560rpx,和宽一样才会正确显示,问下您遇到过这个问题吗?谢谢!
宽:560 高在420-558 保持不变;
只有高在400才会减小。
css: {
mode: “scaleToFill”
},
你好,生成图片过大怎么办
楼主,您好!如下代码所示,将url设置为,https类型的网络图片可以正常加载,将url换成云开发中存储的图片会出错,
报错如下:
VM651:1 Failed to load local image resource /component/components/painter/cloud://xxxxXX/vision-test-image1583682357195.jpg
the server responded with a status of 500 (HTTP/1.1 500 Internal Server Error)
问下您是不是只能使用网络图片和本地图片,不可以使用云开发中存储的图片?
谢谢楼主。
{
type: 'image', url: wx.getStorageSync('imageUrl') || 'https://qiniu-image.qtshe.com/default-avatar20170707.png', css: { top: '32rpx', left: '30rpx', right: '32rpx', width: '688rpx', height: '420rpx', borderRadius: '16rpx' }, },
cloud://cloud-environment-name.6875-cloud-environment-name-1301043156/vision-test-image1578227244217.jpg
url:字段也是填的这个,但是会报错,是不是 没有权限获取该图片?
您好我想请教一下是否可以设置卡片生成文字两行显示且超出隐藏呢?
膜拜!
想问下为什么views里面的东西,ios上没生成