如果需要实现将小程序的页面转为图片,第一步是要先把页面转为canvas,再将canvas转为图片。本人使用的是Wxml2Canvas这个插件。其实最开始使用的是wxml-to-canvas这个官方自带的组件。由于这个组件坑太多,本地调试一切正常,但是到了真机调试就会出现创建画布失败的情况,寻找了很久,最多的方法方法就是添加延时器,或者画布的高度设置在1000px以内。但是都没有什么鬼用,最终无可奈何,只能换个插件,重新写。好惨一男的😥

那我们废话不多说,准备开始搞事情!!

第一步 安装插件

注意 安装之后别忘了构建npm

 npm install wxml2canvas

第二步 引入

import Wxml2Canvas from 'wxml2canvas'; 

第三步 使用

首先需要在页面上创建一个canvas以及需要生成图片的结构

<canvas canvas-id="share"></canvas>

<view class="share__canvas share__canvas1">
    <view class="share__canvas1-text draw_canvas" 
        data-type="text" data-text="这是一段无边距文字">
        这是一段无边距文字
    </view>
</view>

 如果需要使用到图片,其中data-url是图片在canvas显示的地址,即:

<image class="draw_canvas" 	data-type="image" 
    data-url="/static/share/friend_logo.png" 
    data-delay="1" mode="aspectFit" src="/static/share/friend_logo.png"></image>

其中,还有text标签可以使用,必填属性为data-type,声明此标签的在canvas中展示类型,每个标签都有data-top和data-left的属性,分别代表元素参照与自身位置的偏移值。 需要注意的是,data-text是生成的canvas中显示的文字,可以理解为标签的自定义属性,也可以接受变量等。


写入事件,用于获取id为wxml-canvas的宽高,这里的获取的元素的宽高就是将来生成canvas的父元素,获取之后触发draw函数。

//动态获取画制作元素的宽高
drawCanvas: function () {
    const query = wx.createSelectorQuery().in(this);
    query.select('#wxml-canvas').fields({
        size: true,
        scrollOffset: true
    }, data => {
        let width = data.width;
        let height = data.height;
        this.width = width;
        this.height = height;
        setTimeout(() => {
            this.draw()
        }, 1500);
}).exec();

draw函数: 

  draw() {
    let that = this

    //创建wxml2canvas对象
    let drawImage = new Wxml2Canvas({
      element: 'share', // canvas节点的id,
      obj: that, // 在组件中使用时,需要传入当前组件的this
      width: this.width * 2, // 宽高
      height: this.height * 4,
      background: '#fff', // 默认背景色
      progress(percent) { // 绘制进度
      },
      finish(url) {
        console.log("创建的图片", url);
      },
      error(res) {
        console.log(res);
        // uni.hideLoading()
        // 画失败的原因
      }
    }, this);
    let data = {
      //直接获取wxml数据
      list: [{
          type: 'wxml',
          class: '.long_friend  .draw_canvas',
          limit: '.long_friend ',
          x: 0,
          y: 0
        } ]
    }
  //传入数据,画制canvas图片
  drawImage.draw(data, this);
},

解读draw函数

创建wxml2canvas对象

这一步是为了创建wxml2canvas对象,其中传入的参数有三个,第一个参数为一个对象option。第二个参数为创建图片成功时的回调函数,成功时的回调函数第一个参数为图片的地址。第三个参数为失败时的回调函数,会返回失败原因以及状态码,第四个参数传this,是为了防止“canvasToTempFilePath: fail canvas is empty ”报错,报这个错是因为调取wx.canvasToTempFilePath 接口获取不到canvas,同样的需要传入上下文的this。

其中option的宽高,也是生成图片的宽高,我将其设置为元素的初始宽度的两倍,是因为如果是等比的话,图片会模糊。如果发现将宽高*2还是出现图片糊的情况,可以适当调整倍数。

 //创建wxml2canvas对象
    let drawImage = new Wxml2Canvas({
      element: 'share', // canvas节点的id,
      obj: that, // 在组件中使用时,需要传入当前组件的this
      width: this.width * 2, // 宽高
      height: this.height * 2,
      background: '#fff', // 默认背景色
      progress(percent) { // 绘制进度
      },
      finish(url) {
        console.log("创建的图片", url);
      },
      error(res) {
        console.log(res);
        // uni.hideLoading()
        // 画失败的原因
      }
    }, this);

初始化属性option,其属性属性如下:

属性名类型默认值是否必填说明
elementString“”画布的id
widthNumber0画布的宽,以iphone6的375为基准,其他机型按比例自动设置实际宽度
heightNumber0画布的高,同上
destZoomNumber3输出的图片的像素密度,不建议传值,如果需要控制图片大小,可以适当减小
zoomNumber1画布整体缩放比例,不建议传值,会覆盖各种机型的适配
translateXNumber0画布整体横向位移
translateYNumber0画布整体纵向位移
heightNumberheight * 2输出的图片的高度
backgroundString#ffffff画布的整体背景色
gradientBackgroundObjectnull画布整体的渐变背景色
finishFunctionnull绘制成功后回调函数, 返回值url,绘制图片的本地路径
progressFunctionnull绘制进度,返回值percent,0-100
errorFunctionnull绘制失败后回调函数,返回值object,包含具体原因

 绘制失败的原因如下:

错误码原因说明
errcodeerrmsge
1000save canvas error保存图片失败
1001download pic error预下载图片失败
1002drawRect error绘制矩形失败
1003drawImage error绘制图片失败
1004drawText error绘制文本失败
1005drawCircle error绘制圆形图片失败
1006drawCircleImage error绘制圆形失败
1007drawLine error绘制线条失败
1008drawWxml error绘制Wxml失败
1009drawWxml preLoadImage error预下载Wxml图片失败

表格数据转载自:https://github.com/liudongyun1215/wxml2canvas

函数内声明的data对象:

这里的type可以为矩形(rect),圆形(circle),线条(line),图片(image),文本(text)等,声明type为wxml时,会查询绘制元素节点的样式并绘制,class是待查询绘制的节点类名,会查询所有相同的类名。而limit是下面x和y的参考元素,故x和y就是class中元素参照limit祖先元素的偏移值。其更多属性参照与:https://github.com/liudongyun1215/wxml2canvas

let data = {
      //直接获取wxml数据
      list: [{
          type: 'wxml',
          class: '.share__canvas1 .draw_canvas',// draw_canvas指定待绘制的元素
          limit: '.share__canvas1',// 限定绘制元素的范围,取指定元素与它的相对位置
          x: 0,
          y: 0
        } ]
    }

好啦,这就是小谭今天要分享的内容,总结一下,其实这个功能看起来很麻烦,但是只要把思路理清楚在一步步实现就行。说个题外话,wx小程序官方自带组件的问题其实还是蛮坑的。所以,要慎用!血的教训,太惨了。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐