canvas自由绘制画笔的核心是监听鼠标或触摸事件,持续记录坐标点并用lineto连接、stroke渲染,需结合beginpath、moveto、linecap/linejoin优化视觉,辅以距离阈值节流、插值、坐标偏移修正及压感支持等细节提升流畅性与真实感。

Canvas 实现自由绘制画笔,核心是监听鼠标(或触摸)事件,持续记录坐标点,并用 lineTo 连接这些点形成路径,再用 stroke 渲染。关键在于平滑、低延迟、支持压感(可选)和防抖优化。
基础事件绑定与路径绘制
需要监听 mousedown、mousemove、mouseup(桌面)或 touchstart、touchmove、touchend(移动端)。按下时开始新路径,移动时不断添加点,抬起时结束绘制。
- 使用
beginPath()开启新路径,避免多条线意外连接 - 首次移动时用
moveTo(x, y)定位起点,后续用lineTo(x, y)绘制线段 - 调用
stroke()渲染当前路径,别忘了设置lineCap: 'round'和lineJoin: 'round'让线条更自然 - 记得在
mousedown或touchstart中保存初始坐标,防止首次mousemove跳变
提升流畅度:节流与插值
高频 mousemove 可能导致点过密或卡顿,需节流;而过于稀疏又会让线条锯齿明显。推荐用“距离阈值”代替固定时间节流:
- 只在两点间距离超过阈值(如 2–5px)时才添加新点,兼顾性能与顺滑
- 对快速移动的场景,可在相邻点之间做简单线性插值(补中间点),缓解“虚线感”
- 启用
ctx.lineDashOffset配合动画可模拟真实画笔拖尾效果(非必需但增强体验)
支持触控与响应式适配
移动端需处理 touch 事件,并修正坐标偏移:
- 用
event.touches[0].clientX/Y获取触点,而非clientX/Y - 通过
canvas.getBoundingClientRect()获取 canvas 相对于视口的位置,减去该偏移得到准确画布坐标 - 设置
canvas.style.width/height时,务必同步调整canvas.width/height像素尺寸,否则缩放会导致坐标错乱 - 禁用双指缩放:
event.preventDefault()在touchstart和touchmove中(注意不要影响滚动)
进阶:模拟真实画笔质感
纯直线连接太“机械”,可通过以下方式增强表现力:
- 根据移动速度动态调整线宽:速度快则细,慢则粗(用上一帧距离除以时间估算速度)
- 用贝塞尔曲线替代直线连接(如
quadraticCurveTo),让转折更柔和 - 叠加半透明图层实现“墨迹扩散”效果:多次用低透明度绘制同一路径
- 接入
getPressure()(PointerEvent API)获取压感数据,映射到线宽或透明度(需硬件支持)
不复杂但容易忽略细节,把事件、坐标、路径管理和渲染节奏理清楚,就能做出响应灵敏、视觉自然的自由画笔。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











