小程序利用wxml-to-canvas生成分享海报的记录

1,321 阅读1分钟

wxml-to-canvas是微信封装的canvas组件能跳过麻烦的canvas定义

wxml页面

<van-overlay show="{{ sharevisble }}">
  <view class="overlayBox">
    <!-- 这个src是生成的海报地址 -->
    <image src="{{src}}" 	mode="aspectFit" style="width: {{width/1.5}}px; height: {{height/1.5}}px;display:block;"></image>
    <view style="width:100%;margin-top:50rpx">
      <button class="save" bindtap="handleSave">保存图片至本地</button>
    </view>
  </view>
</van-overlay>
<!-- canvas  canvas元素 宽高一定要设置好 并且让元素显示在屏幕外-->
<wxml-to-canvas width="375" height="650" class="widget" style="margin-left:105vw;" ></wxml-to-canvas>

wxss

page {
  width: 100%;
  height: 100%;
  overflow-x:hidden;
}

json

"usingComponents": {
    "wxml-to-canvas": "wxml-to-canvas"
  },

js

base图片转缓存地址的方法
import { base64src } from '../../plugin/utils/base64src.js'
//⚠️海报内容和样式
const {
  wxml,
  style
} = require('./canvas.js');
Router({
/**
   * 页面的初始数据
   */
  data: {
    sharevisble: false,
    src: "", //生成的canvas内存地址
    erweima: '',//读取得到后端给的分享码
  },
  //========canvas=======
  //第一步渲染元素到canvas
 async renderToCanvas() {
    let erweima = this.data.erweima
    let src = await base64src(erweima, res => {
      console.log(res)
      return res // 返回图片地址,直接赋值到image标签即可
    });
    const _wxml = wxml(src);
    console.log(_wxml);
    //获取canvas容器
    setTimeout(() => {
      //渲染到 canvas,传入 wxml 模板 和 style 对象,返回的容器对象包含布局和样式                            
      //信息。

      this.widget = this.selectComponent(".widget");
      const p1 = this.widget.renderToCanvas({
        wxml: _wxml,
        style,
      });
      p1.then((res) => {
        console.log("container", res.layoutBox);
        this.container = res;
        this.extraImage();
        wx.hideLoading();
        this.setData({
          sharevisble: true
        });
      });
    }, 500);
  },
  //第二步 canvas的图片内存地址
  extraImage() {
    const p2 = this.widget.canvasToTempFilePath();
    p2.then((res) => {
      console.log(res);
      this.setData({
        src: res.tempFilePath,
        width: this.container.layoutBox.width,
        height: this.container.layoutBox.height,
      });
    });
    // .then(() => this.handleSave())
  },
  handleSave() {
    console.log("保存");
    const {
      src
    } = this.data;
    const that = this;
    console.log(src);
    if (src) {
      this.saveImageToPhotosAlbum({
        filePath: src,
      }).then(() => {
        wx.showToast({
          icon: "none",
          title: "分享图片已保存至相册",
          duration: 2000,
          complete: function () {
            that.setData({
              sharevisble: false
            });
          },
        });
      });
    }
  },
  saveImageToPhotosAlbum(option) {
    return new Promise((resolve, reject) => {
      wx.saveImageToPhotosAlbum({
        ...option,
        success: resolve,
        fail: reject,
      });
    });
  },
  //========canvasEND=======

两个引入的js

canvas 海报的模板样式

canvas.js

const wxml = ( erweima ) => {
	return `
	<view class="container" >
  <view class="imgContainer">
      <image class="img" src="xxxx"></image>
      <image class="erweima" src="${erweima}"></image>
  </view>
</view>
	`
}

const style = {
	container: {
		width: 375,
		height: 630,
	},
	itemBox: {
		width: 80,
		height: 60,
	},
	imgContainer: {
		position: "relative",
	},
	img: {
		width: 375,
		height: 630,
	},
	erweima: {
		width: 80,
		height: 80,
		position: "absolute",
		bottom: 10,
		left: 10,
	},
}

module.exports = {
	wxml,
	style
}

base64转内存地址 否则不能在wxml模板渲染中显示图片

base64src.js


const fsm = wx.getFileSystemManager();
const FILE_BASE_NAME = 'tmp_base64src'; //自定义文件名
export const base64src = (base64data, cb) =>  {
  const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
  if (!format) {
    return (new Error('ERROR_BASE64SRC_PARSE'));
  }
  const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
  const buffer = wx.base64ToArrayBuffer(bodyData);
  
	

	return new Promise((resolve, reject) => {

    fsm.writeFile({
			filePath,
			data: buffer,
			encoding: 'binary',
			success() {
				cb(filePath);
				resolve(cb(filePath))
			},
			fail() {
			//	return (new Error('ERROR_BASE64SRC_WRITE'));
				reject(new Error('ERROR_BASE64SRC_WRITE'))
			},
		});
	})
}