微信小程序画布wx.createCanvasContext()接口停⽌维护及迁移替代方案

接口调整

微信小程序从基础库 2.9.0 开始,旧的画布API wx.createCanvasContext() 接口停止维护,请使用 Canvas 代替。

新 Canvas 2D 接口(需指定 type 属性),同时支持同层渲染

新画布canvas接口

跳转URL:https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html

旧版 Canvas 迁移指南

小程序的旧版 canvas 接口已经不再维护,本指南将指引如何迁移至新版 Canvas 2D 接口。

特性差异

旧版 Canvas 接口 Canvas 2D 接口
同层渲染 不支持 支持
api支持 部分支持 支持全部 Web 标准
绘制 异步绘制 同步绘制
性能

迁移步骤

第一步:修改 WXML

旧版代码

<canvas canvas-id="myCanvas" />

修改成如下代码

<canvas id="myCanvas" type="2d" />

旧版 canvas 接口使用 canvas-id 属性唯一标识 canvas;新版 Canvas 2D 可直接使用 id 标识。

另外需要给 canvas 添加 type="2d" 属性标识为新版 Canvas 2D 接口。

第二步:修改获取 CanvasContext

旧版代码

const context = wx.createCanvasContext('myCanvas')

修改成如下代码

wx.createSelectorQuery()
    .select('#myCanvas') // 在 WXML 中填入的 id
    .node(({ node: canvas }) => {
        const context = canvas.getContext('2d')
    })
    .exec()

旧版 canvas 接口使用 wx.createCanvasContext 同步获取 CanvasContext。

新版 Canvas 2D 接口需要先通过 SelectorQuery 异步获取 Canvas 对象,再通过 Canvas.getContext 获取渲染上下文 RenderingContext。

第三步:画布大小初始化

旧版 canvas 接口的画布大小是根据实际渲染宽度决定的,开发者无法修改。

新版 Canvas 2D 接口允许开发者自由修改画布的逻辑大小,默认宽高为 300*150。

不同的设备上,存在物理像素和逻辑像素不相等的情况,所以一般我们需要用 wx.getWindowInfo 获取设备的像素比,乘上 canvas 的实际大小。

// 旧版 canvas 不能修改宽高
wx.createSelectorQuery()
    .select('#myCanvas') // 在 WXML 中填入的 id
    .fields({ node: true, size: true })
    .exec((res) => {
        // Canvas 对象
        const canvas = res[0].node
        // Canvas 画布的实际绘制宽高
        const renderWidth = res[0].width
        const renderHeight = res[0].height
        // Canvas 绘制上下文
        const ctx = canvas.getContext('2d')

        // 初始化画布大小
        const dpr = wx.getWindowInfo().pixelRatio
        canvas.width = renderWidth * dpr
        canvas.height = renderHeight * dpr
        ctx.scale(dpr, dpr)
    })

第四步:修改绘制方法

旧版 canvas 接口绘制需要调用 CanvasContext.draw 才会进行绘制,并且绘制过程是异步的,需要等待绘制完成回调才能进行下一步操作。

新版 Canvas 2D 接口不再需要调用 draw 函数,所有绘制方法都会同步绘制到画布上。

需要注意的是 CanvasContext.draw 函数第一个参数控制在绘制前是否保留上一次绘制(默认值为 false,即不保留),若设置为 false,则迁移至新接口后,需要在绘制前通过 clearRect 清空画布。

// 若干绘制调用
context.fillRect(0, 0, 50, 50)
context.fillRect(20, 20, 50, 50)

context.draw(false, () => {
    // 这里绘制完成
    console.log('draw done')
})

//
// 修改为以下
//

// 绘制前清空画布
context.clearRect(0, 0, canvas.width, canvas.height)
// 若干绘制调用
context.fillRect(0, 0, 50, 50)
context.fillRect(20, 20, 50, 50)

// 这里绘制完成
console.log('draw done')

第五步:修改图片绘制

旧版 canvas 接口 CanvasContext.drawImage 直接传入图片 url 进行绘制。

新版 Canvas 2D 接口需要先通过 Canvas.createImage 创建图片对象,onload 图片加载完成回调触发后,再将图片对象传入 context.drawImage 进行绘制。

context.drawImage(
    'https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_wx_logo.png',
    0,
    0,
    150,
    100,
)
//
// 修改为以下
//
const image = canvas.createImage()
image.onload = () => {
    context.drawImage(
        image,
        0,
        0,
        150,
        100,
    )
}
image.src = 'https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_wx_logo.png'

其余接口调整

wx.canvasToTempFilePath

wx.canvasPutImageData

wx.canvasGetImageData

wx.loadFontFace

Bug & Tip

tip:canvas 标签默认宽度300px、高度150px
tip:同一页面中的 canvas-id 不可重复,如果使用一个已经出现过的 canvas-id,该 canvas 标签对应的画布将被隐藏并不再正常工作
tip:请注意原生组件使用限制
tip:开发者工具中默认关闭了 GPU 硬件加速,可在开发者工具的设置中开启“硬件加速”提高 WebGL 的渲染性能
tip: WebGL 支持通过 getContext('webgl', { alpha: true }) 获取透明背景的画布
tip: Canvas 2D(新接口)需要显式设置画布宽高,默认:300*150,最大:1365*1365
bug: 避免设置过大的宽高,在安卓下会有 crash 的问题
tip: iOS 暂不支持 pointer-events
tip: 在 mac 或 windows 小程序下,若当前组件所在的页面或全局开启了 enablePassiveEvent 配置项,该内置组件可能会出现非预期表现(详情参考 enablePassiveEvent 文档)