小程序canvas绘制海报踩坑

441 阅读2分钟

需求:

在微信小程序上有个分享海报,需要用户可以将海报下载分享。

方案:

使用canvas绘制动态海报图

第一阶段:

使用微信小程序canvas语法绘制出海报

问题:在安卓手机上会出现闪退情况

导致原因:海报图过于复杂,绘制笔画过多,小程序canvas性能不佳,导致闪退

解决方法:优化海报样式,减少绘制笔画

第二阶段:

需求:更改海报图样式

问题:安卓手机不再闪退,但是偶发性的出现样式错乱问题

导致原因:微信小程序canvas性能不佳,并且不再维护不稳定

解决方法:使用微信小程序Canvas 2D,需进行旧版语法迁移

截图.png

具体迁移方法:

1、修改wxml

加上type='2d'属性

canvasId改为id

//旧版
<Canvas
   canvasId='posterCanvas'
   style={{ 
            height: bagdHeight ?? 0, 
            width: bagdWidth ?? 0
         }}
   onError={this.onCanvasError.bind(this)}
/>
//新版
<Canvas
   type='2d'
   id='posterCanvas'
   style={{ 
            height: bagdHeight ?? 0, 
            width: bagdWidth ?? 0
         }}
/>
2、修改获取canvas方法
//旧版
let context = Taro.createCanvasContext('posterCanvas', this)
//新版
Taro.createSelectorQuery()
            .select('#posterCanvas')
            .node()
              .exec((res) => {
                const canvas = res[0].node 
                const context = canvas.getContext('2d')
               })
3、画布大小可初始化

旧版的画布大小根据实际渲染宽度决定的,无法修改

新版可修改逻辑大小,默认300*150

不同设备可能存在物理像素和逻辑像素不一样,所以要使绘制出来的图片清晰,需要用像素比乘以画布大小

const dpr = Taro.getSystemInfoSync().pixelRatio

canvas.width = bagdWidth * dpr

canvas.height = bagdHeight1 * dpr

ctx.scale(dpr, dpr)
4、语法兼容

新语法和pc端一致

1)设置文字大小

旧:context.setFontSize(18)

新:context.font = 'normal 400 18px Arial, sans-serif'2)插入图片方法

//旧版

context.drawImage(this.startImg,15+i*18 , imgHeight + 35 + 14 + 6, 13, 12)

//新版-首先创建一个图片对象,图片onload完成后将图片对象传入绘制

const image = canvas.createImage();

image.onload = () => {

     context.drawImage(

       image,

       15+i*18 , imgHeight + 35 + 14 + 6, 13, 12

       )

}

image.src = this.startImg //图片地址
5、画布转化为图片方法兼容

旧版接口传入canvas-id

新版接口传入canvas实例

//旧版:

Taro.canvasToTempFilePath({

      x: 0,

      y: 0,

      width: bagdWidth,

      height: bagdHeight,

      destWidth: bagdWidth,

      destHeight: bagdHeight,

      canvasId: 'posterCanvas',

      success(res) {

        that.setState({

          imgPath: res.tempFilePath

        })

      }

})

//新版:

Taro.canvasToTempFilePath({

      x: 0,

      y: 0,

      width: bagdWidth,

      height: bagdHeight,

      destWidth: bagdWidth,

      destHeight: bagdHeight,

      canvas: canvas,//'posterCanvas',

      success(res) {

        that.setState({

          imgPath: res.tempFilePath,

        })

      }

})