mpvue利用painter生成海报

前言

        最近发现之前做的小程序海报功能突然无法保存和显示,在一些手机上面会出现海报闪烁问题,而且保存后是一片空白。一开始我以为是手机兼容性问题,但是我通过几部测试机,发现同款手机,有些会出现问题,有些不会。找了好久的问题,后来想是不是上传的图片的太大问题,然后百度了一下,发现需要先将网络图片下载再进行海报的生成,我试了一下,完美解决问题。
        虽然说是解决了,但还是不清楚同款手机上,有些会有问题,我猜测可能也和手机性能有关。下面就是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>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值