案例需求
- 页面展示
type="2d"新版 canvas 画布,蓝色背景;手指在画布滑动可以自由绘制线条。 bindtouchstart手指按下,设置绘图起点;bindtouchmove手指移动持续画线。 3.【清空画布】按钮,调用clearRect清除画布全部绘制内容。- ✨作业扩展:增加【改变画笔线条颜色】按钮,点击在红色、绿色之间切换画笔颜色。
完整代码
1.app.json
2.pages/index/index.wxml
3.pages/index/index.wxss
4.pages/index/index.js(含作业扩展切换画笔颜色,增加空判断防报错)
5.app.wxss 全局样式
核心知识点
1.canvas‑2d 组件常用属性
| 属性 | 说明 |
|---|---|
type="2d" | 新版 2D 画布,必须配置;不带 type 的旧版 canvas 已经废弃 |
id | 供createSelectorQuery获取 canvas 节点,id 内横线必须是英文半角- |
bindtouchstart | 手指按下触摸事件,绘图起点 |
bindtouchmove | 手指在画布上移动,持续绘制线条 |
2. 绘图上下文 API
getContext('2d'):获取 2D 绘图上下文 ctx,所有绘图操作由 ctx 完成。- dpr 设备像素比适配:canvas 实际像素 = css 尺寸 × dpr;执行
ctx.scale(dpr,dpr)缩放坐标系,解决线条模糊锯齿。 moveTo(x,y):抬起画笔,移动到起点坐标。lineTo(x,y):定义直线路径到目标坐标。stroke():执行描边,真正把线条绘制到画布。strokeStyle:画笔线条颜色。lineWidth:画笔粗细。lineCap:"round"线条端点圆角;lineJoin:"round"线条拐角圆角。beginPath():开启一条全新路径。clearRect(x,y,w,h):清空指定矩形画布区域。
3.touches 触摸对象
e.touches[0]获取第一个触摸点;.x、.y坐标是相对于 canvas 画布左上角。
4. 作业扩展逻辑
data 中定义strokeColor变量保存当前画笔颜色;点击按钮在红色#ff0000、绿色#00ff00来回切换;每次绘图读取 data 里面保存的颜色。
踩坑实录
坑 1:报错Cannot read property 'node' of null
90% 原因:复制代码带入中文全角横线,canvas 的 id 和 js 选择器不匹配。
- wxml 中
id="my‑canvas"如果是中文长横线,js#my‑canvas选择器找不到节点; - 解决方案:全部替换为英文半角
id="my‑canvas"; - 增加防御判断,res [0] 不存在直接 return,避免程序崩溃。
坑 2:画布线条模糊,锯齿严重
忘记 dpr 像素适配;onReady 回调内部必须乘pixelRatio,并且执行ctx.scale(dpr,dpr)。
坑 3:画不出线条
- 忘记写
stroke();lineTo只是定义路径,stroke()才真正绘制; - 获取 canvas 节点时机:必须放在
onReady的 exec 回调里面;onLoad 阶段 DOM 还未渲染完成拿不到节点; - 复制代码带入中文全角符号,wxml/wxss 报
unexpected character。
坑 4:切换颜色,旧线条跟着变色
canvas 绘制完成的像素是静态;strokeStyle仅控制后续新画的笔迹,旧笔迹不会变化,属于正常现象。
坑 5:清空画布后继续绘画有尾巴残留
clear()内部调用ctx.beginPath(),清空画布同时重置绘制路径。
坑 6:不要使用旧版 canvas 组件
本案例统一用type="2d"新版 canvas;不带 type 属性的旧 canvas 组件官方已经废弃。