微信、支付宝小程序生成海报分享图详解
2019-07-23 本文已影响1人
人类进化又没带我
由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种彩蛋(坑)了吧~
这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能)
咱们不多说,直接上手就是干。
0.png
首先我们新增一个自定义组件,在该组件的json中引入painter
{
"component": true,
"usingComponents": {
"painter": "/painter/painter"
}
}
然后组件的WXML (代码片段在最后)
<view class="share-wrap" wx:if="{{visible}}" catchtouchmove="preventDefault">
<view class="share-back"></view>
<view class="share-container">
<view class="close" bindtap="handleClose"></view>
<image mode="widthFix" src="{{sharePath}}" class="share-image" />
<view class="share-tips">保存图片,叫伙伴们来参与吧</view>
<view class="save-btn" bindtap="handlePhotoSaved"></view>
</view>
</view>
<painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" />
接着组件的WXSS (代码片段在最后)
.share-wrap {
width: 100%;
}
.share-back {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 888;
}
.share-container {
width: 100%;
background: #FFF;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
}
.close {
width: 30rpx;
height: 30rpx;
overflow: hidden;
position: absolute;
right: 64rpx;
top: 64rpx;
}
.close::after {
transform: rotate(-45deg);
}
.close::before {
transform: rotate(45deg);
}
.close::before,
.close::after {
content: '';
position: absolute;
height: 3rpx;
width: 100%;
top: 50%;
left: 0;
margin-top: -2rpx;
background: #9C9C9C;
}
.share-image {
width: 420rpx;
margin: 66rpx auto 0;
display: block;
border-radius: 16rpx;
box-shadow: 0px 4rpx 8px 0px rgba(0, 0, 0, 0.1);
}
.share-tips {
width: 100%;
text-align: center;
color: #3C3C3C;
font-size: 28rpx;
margin: 32rpx 0;
}
.save-btn {
width: 336rpx;
height: 96rpx;
margin: 0 auto 94rpx;
background: url('https://qiniu-image.qtshe.com/20190506save-btn.png') center center;
background-size: 100% 100%;
}
重点来了 JS (代码片段在最后)
Component({
properties: {
//属性值可以在组件使用时指定
isCanDraw: {
type: Boolean,
value: false,
observer(newVal, oldVal) {
newVal && this.drawPic()
}
}
},
data: {
imgDraw: {}, //绘制图片的大对象
sharePath: '', //生成的分享图
visible: false
},
methods: {
handlePhotoSaved() {
this.savePhoto(this.data.sharePath)
},
handleClose() {
this.setData({
visible: false
})
},
drawPic() {
if (this.data.sharePath) { //如果已经绘制过了本地保存有图片不需要重新绘制
this.setData({
visible: true
})
this.triggerEvent('initData')
return
}
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: wx.getStorageSync('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: wx.getStorageSync('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',
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: '生成分享图失败,请刷新页面重试'
})
},
onImgOK(e) {
wx.hideLoading()
this.setData({
sharePath: e.detail.path,
visible: true,
})
//通知外部绘制完成,重置isCanDraw为false
this.triggerEvent('initData')
},
preventDefault() { },
// 保存图片
savePhoto(path) {
wx.showLoading({
title: '正在保存...',
mask: true
})
wx.saveImageToPhotosAlbum({
filePath: path,
success: (res) => {
wx.showToast({
title: '保存成功',
icon: 'none'
})
setTimeout(() => {
this.setData({
visible: false
})
}, 300)
},
fail: (res) => {
wx.getSetting({
success: res => {
let authSetting = res.authSetting
if (!authSetting['scope.writePhotosAlbum']) {
wx.showModal({
title: '提示',
content: '您未开启保存图片到相册的权限,请点击确定去开启权限!',
success(res) {
if (res.confirm) {
wx.openSetting()
}
}
})
}
}
})
setTimeout(() => {
wx.hideLoading()
this.setData({
visible: false
})
}, 300)
}
})
}
}
})
如此一个绘制分享图的自定义组件就完成啦。
效果图如下:
0.jpegtips:
- 暂不支持绘制图片 圆角为:10rpx 0rpx 0rpx 0rpx 类似的。
- 文字居中实现可以看下我代码片段
- 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么一行超出将会展示为省略号