【HarmonyOS 5】鸿蒙实现手写板
本文将从 ArkUI + Canvas + Touch 事件 出发,完整实现一个 HarmonyOS 5 手写板应用,包括基础绘制、平滑曲线、橡皮擦、撤销重做、保存图片、多点触控优化等功能,适合 HarmonyOS NEXT 开发者深入学习。
一、最终效果
最终实现一个完整的手写板:
✅ 手指自由书写
✅ 支持不同颜色
✅ 支持不同画笔粗细
✅ 贝塞尔曲线平滑
✅ 橡皮擦
✅ 撤销(Undo)
✅ 重做(Redo)
✅ 清空画板
✅ 保存图片
✅ 支持高刷新率
效果类似:
---------------------------------------
| |
| 手写区域 |
| |
| *********** |
| *************** |
| ****** |
| |
---------------------------------------
颜色 粗细 橡皮 撤销 重做 清空 保存
二、实现思路
HarmonyOS 中没有现成的 SignatureView。
一般都是:
TouchEvent
│
▼
记录坐标 Point
│
▼
CanvasRenderingContext2D
│
▼
drawLine()
整体流程:
手指移动
│
▼
TouchMove
│
▼
记录Point
│
▼
Canvas绘制
│
▼
刷新Canvas
三、创建项目
DevEco Studio
Stage Model
ArkTS
API 18
HarmonyOS 5
页面:
pages
Index.ets
四、准备Canvas
首先创建 Canvas。
Canvas(this.context)
.width('100%')
.height('100%')
需要:
private context = new CanvasRenderingContext2D();
完整:
@State
private context: CanvasRenderingContext2D =
new CanvasRenderingContext2D();
五、定义Point
class Point{
x:number
y:number
constructor(x:number,y:number){
this.x=x
this.y=y
}
}
保存轨迹:
private points:Array<Point>=[]
六、监听Touch
Canvas 支持:
Touch Down
Touch Move
Touch Up
例如:
Canvas(this.context)
.onTouch((event)=>{
})
判断事件:
switch(event.type){
case TouchType.Down:
break;
case TouchType.Move:
break;
case TouchType.Up:
break;
}
七、开始绘制
按下:
case TouchType.Down:
this.points=[]
this.points.push(
new Point(
event.touches[0].x,
event.touches[0].y
))
八、移动绘制
Move:
this.points.push(
new Point(
event.touches[0].x,
event.touches[0].y
))
然后:
this.draw()
九、Canvas画线
draw(){
if(this.points.length<2){
return
}
let p1=this.points[this.points.length-2]
let p2=this.points[this.points.length-1]
this.context.beginPath()
this.context.moveTo(
p1.x,
p1.y
)
this.context.lineTo(
p2.x,
p2.y
)
this.context.stroke()
}
即可实现最基础手写。
十、设置画笔
颜色:
this.context.strokeStyle="blue"
宽度:
this.context.lineWidth=6
圆角:
this.context.lineCap="round"
连接:
this.context.lineJoin="round"
效果提升很多。
十一、平滑曲线
普通 lineTo 会有锯齿。
推荐:
QuadraticCurve
使用:
quadraticCurveTo()
例如:
context.quadraticCurveTo(
cx,
cy,
x,
y
)
这样可以实现圆润书写。
十二、贝塞尔算法
实际开发一般采用:
P0
P1
P2
计算:
中点
↓
控制点
↓
Bezier
公式:
M=(P1+P2)/2
然后:
quadraticCurveTo(
P1,
M
)
手感接近微信签名板。
十三、动态粗细
速度越快:
线越细
速度慢:
线越粗
计算:
distance
/
time
得到:
velocity
例如:
width=maxWidth-velocity
再限制:
Math.max(
2,
Math.min(
8,
width
))
十四、颜色切换
定义:
@State
private color="black"
绘制前:
context.strokeStyle=this.color
按钮:
Button("红色")
点击:
this.color="red"
即可。
十五、画笔粗细
例如:
Slider({
value:5,
min:1,
max:20
})
改变:
this.lineWidth=value
十六、橡皮擦
橡皮其实不是:
删除
而是:
画白线
例如:
strokeStyle="white"
或者:
globalCompositeOperation
设置:
destination-out
即可真正擦除。
十七、Undo撤销
保存每一笔:
Array<Path>
例如:
paths.push(
currentPath
)
撤销:
paths.pop()
然后:
重新绘制所有Path
十八、Redo重做
准备:
undoStack
redoStack
撤销:
undo
↓
redoStack.push()
恢复:
redo
↓
undoStack.push()
即可。
十九、清空画板
Canvas:
clearRect(
0,
0,
width,
height
)
同时:
paths.clear()
二十、保存图片
HarmonyOS 可以导出 PixelMap。
一般流程:
Canvas
↓
ImageBitmap
↓
PixelMap
↓
File
↓
相册
保存:
save()
即可生成 PNG。
二十一、多点触控
建议:
仅响应第一根手指
例如:
event.touches[0]
避免双指造成轨迹混乱。
二十二、性能优化
推荐:
1、减少 redraw
不要 Move 一次:
clear
↓
全部重画
而是:
新增一段
↓
直接绘制
效率更高。
2、对象复用
不要:
new Point()
几万次。
可以对象池。
3、requestAnimationFrame
统一刷新。
不要:
TouchMove
↓
立即刷新
而:
TouchMove
↓
缓存
↓
下一帧刷新
4、路径缓存
保存:
Path2D
减少 CPU。
5、GPU 加速
HarmonyOS Canvas 默认支持 GPU。
无需自己处理。
二十三、项目目录
entry
│
├──pages
│ Index.ets
│
├──model
│ Point.ets
│ Path.ets
│
├──viewmodel
│ DrawManager.ets
│
├──utils
│ BezierUtil.ets
│
├──common
│ ColorUtil.ets
│
└──resources
二十四、完整架构
TouchEvent
│
▼
DrawManager
│
▼
Point
│
▼
Bezier
│
▼
Canvas
│
▼
Render
采用这种分层后,可以方便扩展:
-
手写签名
-
涂鸦板
-
白板协作
-
批注工具
-
图片标注
-
PDF 批注
-
教学画板
二十五、总结
HarmonyOS 5 实现手写板的核心在于 Touch 事件 + Canvas 绘制 + 路径管理。一个完整的高质量手写板通常包含以下能力:
| 功能 | 推荐实现方式 |
|---|---|
| 手写绘制 | TouchEvent + Canvas |
| 平滑笔迹 | quadraticCurveTo() 或贝塞尔曲线 |
| 动态笔锋 | 根据书写速度动态调整线宽 |
| 橡皮擦 | destination-out 或背景色覆盖 |
| 撤销/重做 | 路径栈(Undo/Redo)管理 |
| 清空画板 | clearRect() + 清空路径数据 |
| 保存图片 | 导出 PixelMap 后保存为 PNG |
| 性能优化 | 增量绘制、对象复用、按帧刷新、路径缓存 |
对于生产级项目,建议将 绘制逻辑、路径模型、贝塞尔算法、工具栏状态、Canvas 渲染 解耦,实现 MVC 或 MVVM 架构,这样更易维护,也便于后续扩展签名、批注、协作白板等高级功能。
更多推荐

所有评论(0)