一、引言
绘图交互一直是小程序开发中最能体现“动手能力”的场景之一。本文基于案例《canvas组件》,介绍如何用小程序的 canvas 2D 接口实现一个自由绘图板:手指在画布上滑动即可留下线条,支持一键清空画布,并进一步拓展了“点击按钮切换画笔颜色”的功能。
二、案例效果
小程序启动后,页面上呈现一块蓝色画布,下方有两个按钮。用手指(或鼠标)在画布上按住拖动,就能画出连续的线条;点击“清空画布”按钮,画布恢复空白;点击拓展加入的“改变画笔颜色”按钮,画笔在红色、绿色、蓝色、黄色、白色之间循环切换,可以画出五彩的图案。
三、核心思路
整个绘图功能的实现可以拆成三步:拿到画布、监听触摸、沿轨迹画线。
第一步是初始化画布。canvas 是一个相对特殊的组件,必须先通过选择器查询拿到它对应的原生节点,再用节点对象创建“二维绘图上下文”。这里有一个容易被忽视的细节:手机屏幕的物理像素和逻辑像素并不一致,两者的比值叫设备像素比。如果不做处理,画出来的线条会显得模糊。正确做法是把画布的真实宽高设为显示尺寸乘以像素比,再对绘图上下文做等比缩放,这样坐标依然按逻辑像素计算,但线条是清晰的。
第二步是响应触摸。canvas 组件支持触摸开始和触摸移动两个事件。触摸开始时,记录落点坐标作为线条起点,同时设置线条的样式——颜色、线宽、端点和拐角的圆滑程度;触摸移动时,把新的坐标点接到路径上并描边,连续不断的移动事件就形成了跟随手指的曲线。
第三步是清屏。清空画布的做法是先开启一条新路径,再用清空矩形指令把整个画布的像素全部抹掉,画布就恢复成初始的背景色。
四、拓展功能:动态切换画笔颜色
在基本功能之上,我增加了一个“改变画笔颜色”按钮。做法是预先定义一个颜色数组,再维护一个当前颜色下标,每次点击按钮,下标加一并对数组长度取余,实现循环切换。绘制线条时,颜色不再写死,而是从数组里按下标取值,于是每按一次按钮,接下来画出的线条就换一种颜色。为了让用户感知到操作生效,切换时还会弹出一个轻提示。
五、踩坑记录(重点)
画布节点取不到,画不了线:这是本案例最大的坑。获取 canvas 节点必须在页面“就绪”生命周期之后进行,如果过早获取,节点还不存在。此外,官方提供了两种查询写法,其中一种带节点信息的写法在部分环境下拿不到结果,而更直接、更稳的方式是先取节点、再单独查一次尺寸。我在开发中就遇到了触摸事件正常触发、却始终画不出线的情况,排查后发现绘图上下文一直是空的——因为初始化没成功。解决办法是在触摸处理函数开头加一道判断:上下文没就绪就直接返回,同时打印日志,问题一目了然。
渲染引擎要选对:小程序默认的 Skyline 渲染引擎对部分旧式组件和写法支持不完整,本项目把渲染引擎改回 webview 后,画布的节点查询才恢复正常。配置文件里去掉相关声明、显式指定 webview 即可。
改完代码要清缓存:开发者工具有时不会立刻应用配置变更,遇到“明明改对了还是不行”的情况,先清除全部缓存再重新编译,往往能省下半小时的纠结。
线条颜色非法会导致看不见:如果颜色值取到了未定义的下标,描边颜色会变成非法值,线条实际没画出来但没有报错,很容易误以为坐标计算有问题。用日志确认颜色取值是有效的排查手段。
六、总结
这个案例代码量不大,却完整走通了小程序绘图的核心链路:节点查询、上下文创建、像素比适配、触摸事件、路径绘制与清屏。更重要的是,调试过程让我体会到小程序开发的一个通用方法论——用日志确认每一步的中间状态,把“看不见的失败”变成“看得见的数据”。在此基础之上,还可以继续扩展撤销笔画、选择线宽、保存画布为图片等功能,有兴趣的读者可以自行尝试。