微信小程序画布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'
其余接口调整
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 文档)