前言
最近发现之前做的小程序海报功能突然无法保存和显示,在一些手机上面会出现海报闪烁问题,而且保存后是一片空白。一开始我以为是手机兼容性问题,但是我通过几部测试机,发现同款手机,有些会出现问题,有些不会。找了好久的问题,后来想是不是上传的图片的太大问题,然后百度了一下,发现需要先将网络图片下载再进行海报的生成,我试了一下,完美解决问题。
虽然说是解决了,但还是不清楚同款手机上,有些会有问题,我猜测可能也和手机性能有关。下面就是mpvue使用painter的具体实现,主要是将一张背景图片和一张二维码合成一张海报。
海报实现
painter的使用非常简单,只需要一串json数据就可以生成海报,而且提供@imgOK回调来获取生成后的海报路径。
一、首先引入painter
可以先去GitHub上面直接下载,最好放在static 里
git submodule add https://github.com/Kujiale-Mobile/PainterCore.git static/painter
然后在需要使用的mpvue页面上引入
usingComponents: {
'painter': '/static/painter/painter'
}
二、painter的使用
在页面上使用
<div class="painter-pic">
<painter
v-if="Object.keys(templateJson).length!=0"
@imgOK="onImgOk"
:imgErr="onImgErr"
:palette="templateJson"
/>
<div class="save-btn" @click="save()">保存图片</div>
</div>
主要是图片的下载,我将两张网络图片在进入页面时就进行下载
onLoad: function(options) {
let data=JSON.parse(decodeURIComponent((options.item)));
var seft=this
//下载背景图
wx.downloadFile({
url:data.posterSetupId.posterPhoto,
success(res){
seft.posterPhoto=res.tempFilePath
}
})
//下载二维码图片
wx.downloadFile({
url:data.qrcodePath,
success(res){
seft.qrcodePath=res.tempFilePath
}
})
this.getSharePic()
},
然后写个定时器判断图片是否下载成功,成功就开始绘制海报
getSharePic(){
wx.showLoading({
title: "正在生成海报",
mask: true
});
//海报动态生成,需要判断图片是否下载到本地再进行渲染
this.timeOut=setInterval(() => {
this.createPoster() //绘制海报
}, 1500);
},
//绘制海报
createPoster() {
this.templateJson= {};
// 绘制样式,判断图片是否已经生成
if(this.posterPhoto && this.qrcodePath){
this.templateJson= {
background: "#ffffff",
width: "548rpx",
height: "883rpx",
views: [
{
type: "image",
url: this.posterPhoto,
css: {
top: "0rpx",
left: "0rpx",
width: "548rpx",
height: "883rpx"
}
},
{
type: "image",
url: this.qrcodePath,
css: {
top: "740rpx",
right: "25rpx",
width: "120rpx",
height: "120rpx"
}
}
]
};
//将加载框和定时器关掉
wx.hideLoading();
clearInterval(this.timeOut)
}else{
//8*1.5s=12s 在12s后还没有生成海报就停止绘制
if(this.count>8){
wx.hideLoading();
wx.showToast({
title:'生成海报失败',
icon:'none'
})
clearInterval(this.timeOut)
this.count=0
setTimeout(()=>{
wx.navigateBack()
},1500)
}else{
this.count++
}
}
},
海报绘制成功后可以通过 @imgOK 回调获取海报路径
onImgOk(e) {
this.shareImg = e.mp.detail.path; // 生成的图片路径
},
二、保存海报
save() {
wx.showLoading({
title: "正在领取",
mask: true
});
setTimeout(()=>{
wx.hideLoading();
if(this.shareImg){
wx.saveImageToPhotosAlbum({
filePath: this.shareImg,
success: res => {
wx.showModal({
title: "保存成功",
content: "海报已经成功保存到你的相册了",
success: res => {
wx.navigateBack()
console.log(res)
},
error: err => {
wx.navigateBack()
console.log(err)
}
});
},
fail: err => {
console.log(err)
}
});
}
},500)
},
这样海报就生成成功,生成后的效果如下图
最后贴出本页面完整代码
<template>
<div class="container">
<div class="painter-pic">
<painter
v-if="Object.keys(templateJson).length!=0"
@imgOK="onImgOk"
:imgErr="onImgErr"
:palette="templateJson"
/>
<div class="save-btn" @click="save()">保存图片</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
item:'',
timeOut:'',
count:0,
posterPhoto: "",
qrcodePath: "",
templateJson: {},
shareImg: "",
};
},
methods: {
onImgErr(e){
console.log(e)
},
onImgOk(e) {
this.shareImg = e.mp.detail.path; // 生成的图片路径
},
getSharePic(){
wx.showLoading({
title: "正在生成海报",
mask: true
});
//海报动态生成,需要判断图片是否下载到本地再进行渲染
this.timeOut=setInterval(() => {
this.createPoster()
}, 1500);
},
createPoster() {
this.templateJson= {};
// 绘制样式,判断图片是否已经生成
if(this.posterPhoto && this.qrcodePath){
this.templateJson= {
background: "#ffffff",
width: "548rpx",
height: "883rpx",
views: [
{
type: "image",
url: this.posterPhoto,
css: {
top: "0rpx",
left: "0rpx",
width: "548rpx",
height: "883rpx"
}
},
{
type: "image",
url: this.qrcodePath,
css: {
top: "740rpx",
right: "25rpx",
width: "120rpx",
height: "120rpx"
}
}
]
};
//将加载框和定时器关掉
wx.hideLoading();
clearInterval(this.timeOut)
}else{
//8*1.5s=12s 在12s后还没有生成海报就返回原页面
if(this.count>8){
wx.hideLoading();
wx.showToast({
title:'生成海报失败',
icon:'none'
})
clearInterval(this.timeOut)
this.count=0
setTimeout(()=>{
wx.navigateBack()
},1500)
}else{
this.count++
}
}
},
save() {
wx.showLoading({
title: "正在领取",
mask: true
});
setTimeout(()=>{
wx.hideLoading();
if(this.shareImg){
wx.saveImageToPhotosAlbum({
filePath: this.shareImg,
success: res => {
wx.showModal({
title: "保存成功",
content: "海报已经成功保存到你的相册了",
success: res => {
wx.navigateBack()
console.log(res)
},
error: err => {
wx.navigateBack()
console.log(err)
}
});
},
fail: err => {
console.log(err)
}
});
}
},500)
},
},
mounted() {
},
onLoad: function(options) {
let data=JSON.parse(decodeURIComponent((options.item)));
var seft=this
wx.downloadFile({
url:data.posterSetupId.posterPhoto,
success(res){
seft.posterPhoto=res.tempFilePath
}
})
wx.downloadFile({
url:data.qrcodePath,
success(res){
seft.qrcodePath=res.tempFilePath
}
})
this.getSharePic()
},
onReachBottom() {
}
};
</script>
<style lang="less" scoped>
.container {
width: 100%;
box-sizing: border-box;
font-size: 14px;
.painter-pic {
width: 100%;
background: #f5f5f5;
padding: 200rpx 100rpx 100rpx 100rpx;
box-sizing: border-box;
.save-btn {
background: rgb(224, 46, 46);
text-align: center;
width: 100%;
box-sizing: border-box;
color: #ffffff;
padding: 20rpx;
border-radius: 10rpx;
margin-top: 20rpx;
font-size: 28rpx;
}
.close-btn {
position: absolute;
width: 54rpx;
height: 54rpx;
right: 50rpx;
top: 240rpx;
border-radius: 50%;
border: 1px solid #fff;
text-align: center;
}
}
}
</style>