需求背景:商品详情页通过点击生成海报弹出海报弹窗,点击弹窗按钮保存海报至相册。
- 安装wxml2canvas依赖,通过微信编译器-工具-npm构建,生成miniprogram_npm文件
2.在需要实现页面的js中引入 wxml2canvas
import Wxml2Canvas from '../../miniprogram\_npm/wxml2canvas/index'
3. wxml部分实现代码块
//生成海报弹窗
<van-popup show="{{showPoster}}" custom-style="width: 90%;overflow:hidden;" round bind:click-overlay="closePoster">
<view class="popup-box" style="border-radius: 20rpx;overflow:hidden;width: 100%;height: 100%;">
//海报canvas
<canvas canvas-id="myCanvas1" style="width: 98%;height:65vh;margin: 10rpx 1% 0rpx;"></canvas>
//点击保存按钮
<view style="margin: 10rpx 0rpx 0rpx;padding: 30rpx;background-color: #2FC0C8;color: #fff;text-align: center;" bindtap="savePoster">保存海报到相册</view>
</view>
</van-popup>
//生成海报模板
<view class="panel" wx:if="{{showPoster}}">
//图片需要加上data-type="image" data-url="图片路径"
<image class="panel-image" src="{{afterUploadImage}}" background-size="cover" data-url="{{afterUploadImage}}" data-type="image" style="height: 550rpx;padding-top: 20rpx;width: 100%;margin: 0rpx auto;"></image>
//文字需要加上data-type="text" data-text="文字内容"
<view class="panel-spec" data-type="text" data-text="{{goods.goodsName}}" style="font-weight: bold;font-size: 34rpx;margin:100rpx 20rpx 50rpx;"></view>
<view class="panel-money" data-type="text" data-text="¥{{productSinglePrice}}" style="color: red;font-size: 33rpx;margin:50rpx 20rpx;"></view>
<view style="display: flex;justify-content: space-between;padding-bottom: 20rpx;width: 100%;">
<view style="display: flex;padding: 20rpx 20rpx;">
<view style="width: 100rpx;height: 100rpx;border-radius: 100rpx;overflow: hidden;">
<image class="panel-avatar-img" data-type="image" src="{{avatarUrl||'/static/images/avatar@no_login.png'}}" data-url="{{avatarUrl||'/static/images/avatar@no_login.png'}}" data-type="image" style="width: 100rpx;height: 100rpx;" data-radius="100"></image>
</view>
<view class="text-content" style="margin-left: 20rpx;">
<view class="panel-user-text" data-type="text" data-text="{{userInfo.nickName||'请授权'}}" style="margin-top: -50rpx;font-weight: bold;font-size: 28rpx;"></view>
<view class="panel-user-more" data-type="text" data-text="扫一扫查看更多详情" style="margin-top: 50rpx;font-size: 24rpx;"></view>
</view>
</view>
<view style="width:50px;height:50px;margin-left: -100rpx;">
<image class="panel-avatar-code" data-type="image" data-url="{{codeImage}}" style="width:70px;height:70px;margin-left: -140rpx;"/>
</view>
</view>
</view>
4.js部分实现代码块
注意:本地图片是可以直接渲染的,链接图片需要保存到本地以后才可渲染,因此如果生成的海报中有接口返回的图片时,需要做先保存获取本地地址再渲染
wx.downloadFile({
//小程序仅支持https的,所以如果图片路径是http的需要加上.replace('http','https')
url: '图片路径',
success: function(res){
let img = res.tempFilePath
if(img){
that.setData({
afterUploadImage:img
})
}else{
that.setData({
afterUploadImage:"",
})
}
},
fail: function (error) {
wx.showToast({
title: error,
icon: 'none'
})
}
})
// 生成海报
drawImage1:function() {
this.setData({
showPoster:true //海报弹窗
})
let self = this;
let drawMyImage = new Wxml2Canvas({
width: self.data.width * 2, // 宽, 以iphone6为基准,传具体数值,其他机型自动适配
height: self.data.height * 2, // 高
obj:self,
element: 'myCanvas1', //海报canvas的canvas-id
background: '#fff',//海报背景色
progress (percent) {
},
finish(url) {
wx.hideLoading()
self.setData({
imgs:url //最终生成海报的图片路径,用于点击保存海报使用
})
},
error (res) {
}
});
//绘制海报的元素
let data = {
list: [
{
type: 'wxml',
class:'.panel .panel-image',
limit:'.panel',
x: 0,
y: 0,
},//图片
{
type: 'wxml',
class:'.panel .panel-spec',
limit:'.panel',
x: 0,
y: 0,
},
{
type: 'wxml',
class:'.panel .panel-money',
limit:'.panel',
x: 0,
y: 0,
},
{
type: 'wxml',
class:'.panel .panel-avatar-img',
limit:'.panel',
x: 0,
y: 0,
},
{
type: 'wxml',
class:'.panel .text-content .panel-user-text',
limit:'.panel',
x: 0,
y: 0,
},
{
type: 'wxml',
class:'.panel .text-content .panel-user-more',
limit:'.panel',
x: 0,
y: 0,
},
{
type: 'wxml',
class:'.panel .panel-avatar-code',
limit:'.panel',
x: 0,
y: 0,
},
]
}
drawMyImage.draw(data,this);
},
5.保存海报图片
savePoster() {
const that = this
wx.saveImageToPhotosAlbum({
filePath: that.data.imgs,
success: function() {
wx.showToast({
title: '保存成功',
icon: 'none',
duration: 1500
});
that.setData({
showPoster:false
})
},
fail(err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny" || err.errMsg === "saveImageToPhotosAlbum:fail authorize no response") {
wx.showModal({
title: '提示',
content: '需要您授权保存相册',
showCancel: false,
success: modalSuccess => {
wx.openSetting({
success(settingdata) {
if (settingdata.authSetting['scope.writePhotosAlbum']) {
wx.saveImageToPhotosAlbum({
filePath: that.data.imgs,
success: function () {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
})
} else {
wx.showToast({
title: '授权失败,请稍后重新获取',
icon: 'none',
duration: 1500
});
}
}
})
}
})
}
}
})
},
到这里就大功告成啦~over