wxml2canvas原生微信小程序生成海报保存图片

808 阅读2分钟

需求背景:商品详情页通过点击生成海报弹出海报弹窗,点击弹窗按钮保存海报至相册。

  1. 安装wxml2canvas依赖,通过微信编译器-工具-npm构建,生成miniprogram_npm文件

a.png

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