
文章分类:设计前沿 发布时间:2026-06-21 原文作者:小程序开发 阅读( )
好,咱们今天就聊聊微信小程序里的 canvas。说实话,我第一次碰这玩意儿的时候,真有点懵。不是因为它难,而是微信文档写得实在太“官方”了,读起来像在看天书——什么“创建画布上下文”“绑定触摸事件”,每个字都认识,连在一起却不知道从哪下手。后来折腾了几个通宵,踩了无数坑,才算摸到点门道。

先说说最基础的东西。微信小程序的 canvas 跟网页版不一样,它有两种模式:2D 模式和旧版 Canvas。2D 模式是微信后来推出的,性能更好,API 也更接近 Web 标准。但问题是,很多教程还停留在旧版,你照着抄代码,跑起来全是报错。我建议新手直接上 2D 模式,别纠结。创建方式其实就两步:先在 WXML 里写个 ``,然后在 JS 里用 `wx.createSelectorQuery()` 找到这个节点,再调用 `node.getContext('2d')` 拿到上下文。这一步卡了我一下午,因为我总想着像网页那样直接用 `document.getElementById`,结果微信根本不认。
拿到上下文之后,真正的乐趣才开始。画矩形、画圆这些基础操作倒不难,难的是你会发现 canvas 的坐标系和网页一样,都是左上角为原点,但微信小程序的屏幕适配却是个大坑。不同手机的尺寸、像素比都不一样,你画出来的图在 iPhone 14 Pro 上可能精致得像艺术品,换到千元安卓机上就会糊成马赛克。解决办法也不复杂——先拿到系统信息里的像素比(`wx.getSystemInfoSync().pixelRatio`),然后把 canvas 的宽高乘以这个比值,再用 CSS 缩放到正常尺寸。这一招我是在一个老程序员博客里看到的,他把它叫“高清屏适配”,听着挺唬人,其实就是多写几行代码。
说到绘图,微信 canvas 有个特别坑的地方:文本渲染逻辑。用 `fillText` 画文字时,默认是从左上角开始的,如果想让文字居中,就得自己算 x、y 坐标。更烦的是,不同字体、不同字号,文字的实际宽度会不一样。微信提供了 `measureText` 方法可以测量文字宽度,但只有在 2D 模式下才能用。我试过一次,在旧版 canvas 里调用它,直接返回 `undefined`,气得我差点摔手机。后来学乖了,每次画文字前都先 `measureText`,再根据宽度调整位置。
动画是 canvas 的重头戏。微信小程序里做动画,最常用的就是 `requestAnimationFrame`。这个 API 跟浏览器里几乎一样,但微信对它的调用频率有限制——在某些低端机上会被降到 30 帧甚至更低。解决办法是手动控制帧率,比如用 `setInterval` 每隔 16 毫秒刷新一次,或者在 `requestAnimationFrame` 的回调里自行计算时间差,超过阈值才重绘。我试过后者,效果还行,但代码量直接翻倍。最让我头疼的是触摸事件。想在 canvas 上拖动图形,就得监听 `touchstart`、`touchmove`、`touchend`。微信的触摸事件返回的坐标是相对于页面,而不是相对于 canvas。你需要先用 `wx.createSelectorQuery` 拿到 canvas 在页面上的偏移量,然后减去这个偏移量,才能得到正确的绘图坐标。这个坑我踩了至少三次,每次都以为自己写错了,查半天才发现是坐标没算对。
性能优化是避不开的话题。如果你只是画个静态图,那没问题。但要是做实时绘图,比如手写板、画图工具,性能问题立马暴露。微信小程序的 canvas 渲染效率远不如网页版,尤其在安卓机上,你画几百条线,CPU 直接飙到 90%。优化手段无非几样:减少重绘区域(只重绘变化的部分)、用离屏 canvas 缓存静态内容、避免频繁调用 `setData`。我试过离屏 canvas,效果确实明显——先在一个隐藏的 canvas 上画好背景,每次主 canvas 刷新时只把离屏 canvas 的内容 `drawImage` 过来,省掉了大部分渲染计算。但微信对离屏 canvas 的支持也有坑——必须先创建离屏 canvas,再获取它的上下文,这个过程比主 canvas 还麻烦。
说说实战中碰到的那些“玄学”问题。有一次,我画了一个图表,在开发者工具里跑得好好的,真机上一测试,图形全变形。查半天发现是因为开发者工具里的 canvas 默认是 2 倍像素比,而我的真机是 3 倍。还有一次,我用了 `ctx.save()` 和 `ctx.restore()` 来管理状态,结果在循环里忘了配对,导致整个画布颜色混乱。最离谱的是,微信对 canvas 的大小有限制——宽度和高度都不能超过 4096 像素,否则直接白屏。我那次画一个超长全景图,差点被这个限制搞崩溃。后来只能把图切成多段,分段渲染再拼起来。
说到底,微信小程序的 canvas 就像个脾气古怪的艺术家——它有自己的一套规则,你必须顺着它的脾气来,才能画出好东西。千万别想着把网页的经验直接套用,否则会踩坑到怀疑人生。但一旦摸透了它的特性,它能带来的惊喜也不少:比如用 canvas 做海报生成、实时滤镜、小游戏,这些在普通视图层很难实现的效果,canvas 都能轻松搞定。
我现在的习惯是,每次写 canvas 代码之前,先把微信官方的 API 文档翻一遍——不是全看,只看与当前功能相关的部分。然后写个最小可复现的 demo,验证 API 在真机上的表现。这个习惯帮我省了至少 80% 的调试时间。如果你刚开始接触微信 canvas,建议也这么做——别急着写大功能,先画个点、画条线、画个圆,把这些基础操作跑通,再慢慢堆叠功能。毕竟,再复杂的画布,也是从第一个像素点开始的。