# 8.5:Canvas画布组件
ArkUI开发框架提供了 Canvas
画布组件支持我们自绘制各种图形的需求,Canvas
的具体绘制是委托给 CanvasRenderingContext2D
实现的, CanvasRenderingContext2D
提供了一系列绘画相关的方法,笔者把 CanvasRenderingContext2D
简单理解成一个画笔,画笔绘制的内容在画布 Canvas
上显示。本节课主要向读者介绍 CanvasRenderingContext2D
的使用。
# 8.5.1:Canvas定义介绍
interface CanvasInterface {
(context?: CanvasRenderingContext2D): CanvasAttribute;
}
2
3
- context:
Canvas
组件创建的时候需要一个CanvasRenderingContext2D
实例,该实例负责在Canvas
上绘制具体内容,比如文本、图片以及各种形状等。
# 8.5.2:Canvas事件介绍
declare class CanvasAttribute extends CommonMethod<CanvasAttribute> {
onReady(event: () => void): CanvasAttribute;
}
2
3
- onReady():
Canvas
组件初始化成功后的回调,绘制相关的操作均在该回调中进行。
简单样例如下所示:
样例运行结果如下图所示:
# 8.5.3:CanvasRenderingContext2D属性介绍
CanvasRenderingContext2D
是 Canvas
的画笔,继承自 CanvasRenderer
,它的常用属性如下所示:
declare class CanvasRenderer extends CanvasPath {
// 绘制图片
drawImage(image: ImageBitmap | PixelMap, dx: number, dy: number): void;
// 绘制矩形
fillRect(x: number, y: number, w: number, h: number): void;
// 绘制文本
fillText(text: string, x: number, y: number, maxWidth?: number): void;
// 测量文本
measureText(text: string): TextMetrics;
// 旋转画布
rotate(angle: number): void;
// 恢复当前绘图上下文
restore(): void;
// 保存当前绘图上下文
save(): void;
// 省略部分API
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CanvasRenderer
提供了丰富的符合业界 W3C 标准规范的 API ,但是从易用性上来有点复杂,笔者也向 OpenHarmony 讨论过这些 API 的易用性 问题 (opens new window),为了方便读者快速实现绘制能力,笔者封装了一个 MiniCanvas (opens new window) 组件,接下来向大家介绍 MiniCanvas (opens new window) 的用法,有关 CanvasRenderer
的详细用法请参考官方文档 (opens new window),笔者就不一一介绍了。
# 8.5.4:MiniCanvas组件介绍
MiniCanvas
组件是笔者基于 Canvas
封装的一个 Mini 版的绘图组件,它屏蔽了 Canvas
内部复杂的调用流程,给读者提供了一系列精简的 API ,具体绘制通过一个 API 就可以搞定,极大的简化了绘制操作,目前该控件还在不断完善中,笔者也欢迎读者使用该控件并为该控件提交PR。
MiniCanvas
提供了一系列 drawXXX()
方法,该方法内需要接收一个 Paint
对象,通过设置 Paint
的参数来实现不同的绘制样式,比如 setColor()
设置绘制颜色,setTextSize()
设置文字大小,setStroke()
设置是否绘制轮廓等,具体样式可以读者可以阅读源码。
# 8.5.4.1:绘制直线
public drawLine(startX: number, startY: number, stopX: number, stopY: number, paint: Paint);
MiniCanvas
提供了 drawLine()
方法绘制直线,它接收起始点坐标(startX,startY)和结束点坐标(stopX,stopY)和一个画笔(paint),画笔(paint)支持设置直线的颜色,粗细等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({ // 使用MiniCanvas组件
onDraw: (canvas) => { // 在onDraw回调方法内绘制图形
let paint = new Paint(); // 创建画笔
paint.setColor(Color.Red.toString()); // 设置画笔颜色
paint.setStrokeWidth(4); // 设置画笔线条粗细
canvas.drawLine(10, 10, 200, 10, paint); // 调用drawLine绘制一条直线
paint.setColor("#aabbcc") // 设置画笔颜色
paint.setStrokeWidth(2); // 设置画笔线条粗细
canvas.drawLine(10, 20, 260, 60, paint); // 调用drawLine绘制一条直线
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
样例运行结果如下图所示:
# 8.5.4.2:绘制文本
public drawText(text: string, x: number, y: number, paint: Paint, maxWidth?: number);
MiniCanvas
提供了 drawText()
方法绘制文本, text 是要绘制的文本内容, x 和 y 表示文本绘制的起始坐标,画笔(paint)支持文本的大小,字体,颜色等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let text = "OpenHarmony"; // 需要绘制的文本
let paint = new Paint() // 创建画笔
paint.setFontSize(vp2px(30)) // 设置字体大小
canvas.drawText(text, 10, 12, paint); // 绘制文本
paint.setColor(Color.Red.toString()) // 设置字体颜色
canvas.drawText(text, 140, 45, paint); // 绘制文本
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
样例运行结果如下图所示:
# 8.5.4.3:绘制圆
public drawCircle(x: number, y: number, radius: number, paint: Paint);
MiniCanvas
提供了 drawCircle()
方法绘制圆, x 和 y 表示圆心坐标, radius 表示圆的半径,画笔(paint)支持设置圆的颜色,是否是圆环以及圆环的粗细。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint()
canvas.drawCircle(90, 45, 30, paint); // 绘制圆,半径30
paint.setColor("#ff0000") // 设置圆的颜色
canvas.drawCircle(170, 45, 30, paint); // 绘制圆
paint.setStroke(true) // 设置绘制圆环
canvas.drawCircle(90, 125, 30, paint); // 绘制圆环
paint.setColor("#000000") // 设置圆环颜色
paint.setStrokeWidth(vp2px(4)) // 设置圆环粗细
canvas.drawCircle(170, 125, 30, paint); // 绘制圆环
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
样例运行结果如下所示:
# 8.5.4.4:绘制椭圆
public drawOval(x: number, y: number, width: number, height: number, paint: Paint);
MiniCanvas
提供了 drawOval()
方法绘制椭圆,x和y表示椭圆所在矩形的左上角坐标, width 和 height 表示椭圆所在矩形的宽高,画笔(paint)支持设置圆的颜色,是否是圆环以及圆环的粗细等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint()
canvas.drawOval(10, 10, 150, 60, paint);
paint.setColor('#ff0000')
canvas.drawOval(170, 10, 150, 60, paint);
paint.setStroke(true)
paint.setColor(Color.Pink.toString())
canvas.drawOval(10, 80, 150, 60, paint);
paint.setColor('#ff0000')
paint.setStrokeWidth(vp2px(3))
canvas.drawOval(170, 80, 150, 60, paint);
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
样例运行结果如下图所示:
# 8.5.4.5:绘制矩形
public drawRect(x: number, y: number, width: number, height: number, paint: Paint);
MiniCanvas
提供了 drawRect()
方法绘制矩形, x 和 y 表示矩形的左上角坐标, width 和 height 表示矩形的宽高,画笔(paint)支持设置矩形的颜色,是否是矩形框以及矩形框的粗细等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint() // 创建画笔
canvas.drawRect(10, 10, 150, 50, paint);
paint.setColor(Color.Pink.toString())
canvas.drawRect(170, 10, 150, 50, paint);
paint.setStroke(true)
canvas.drawRect(10, 70, 150, 50, paint);
paint.setColor('#ff0000')
paint.setStrokeWidth(3)
canvas.drawRect(170, 70, 150, 50, paint);
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
样例运行结果如下所示:
# 8.5.4.6:绘制圆角矩形
public drawRoundRect(x: number, y: number, width: number, height: number, radius: number, paint: Paint);
MiniCanvas
提供了 drawRoundRect()
方法绘制圆角矩形, x 和 y 表示圆角矩形的左上角坐标, width 和 height 表示圆角矩形的宽高, radius 表示圆角大小,画笔(paint)支持设置矩形的颜色,是否是矩形框以及矩形框的粗细等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint()
canvas.drawRoundRect(10, 10, 150, 50, 10, paint);
paint.setColor(Color.Pink.toString())
canvas.drawRoundRect(170, 10, 150, 50, 15, paint);
paint.setStroke(true)
canvas.drawRoundRect(10, 70, 150, 50, 15, paint);
paint.setColor('#ff0000')
paint.setStrokeWidth(3)
canvas.drawRoundRect(170, 70, 150, 50, 10, paint);
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
样例运行结果如下图所示:
# 8.5.4.7:绘制圆弧
drawArc(x: number, y: number, radius: number, startAngle: number, endAngle: number, paint: Paint, counterclockwise?: boolean): void;
MiniCanvas
提供了 drawArc()
方法绘制圆弧, x 和 y 表示圆心坐标, radius 表示圆弧的半径, startAngle 表示圆弧起始角度, endAngle 表示圆弧结束角度,画笔(paint)支持设置圆弧的颜色以及是否实心等。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint(); // 创建画笔
paint.setStroke(true) // 设置空心圆弧
canvas.drawArc(30, 30, 30, 0, 130, paint)
paint.setColor(Color.Red.toString()) // 设置圆弧颜色
canvas.drawArc(100, 30, 30, 0, 130, paint)
paint.setStroke(false) // 设置实心圆弧
canvas.drawArc(170, 30, 30, 0, 130, paint)
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
样例运行结果如下图所示:
# 8.5.4.8:绘制图片
public drawImage(image: ImageBitmap, sx: number, sy: number, sWidth: number, sHeight: number, dx: number, dy: number, dWidth: number, dHeight: number);
MiniCanvas
提供了 drawImage()
方法绘制图片, image 表示要绘制的图片数据源, sx 和 sy 表示从图片的起始点开始绘制, sWidth 和 sHeight 表示选取图片的宽高, dx 和 dy 表示绘制在画布上的起始点坐标, dWidth 和 dHeight 表示绘制图片的区域,简单理解就是把选取的图片区域 Rect(sx, sy, sWidth, sHeight) 绘制在指定的画布区域 Rect(sx, dy, dWidth, dHeight) 中。简单样例如下所示:
@Entry @Component struct MiniCanvasTest {
build() {
Column() {
MiniCanvas({
onDraw: (canvas) => {
let paint = new Paint();
let image = new ImageBitmap("pages/test.jpg"); // 创建ImageBitmap实例
canvas.drawImage(image, 0, 0, 500, 500, 10, 10, 250, 100, paint) // 绘制图片
}
})
}
.size({width: '100%', height: "100%"})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
样例运行结果如下图所示:
以上就是 MiniCanvas (opens new window) 的简单使用,欢迎读者使用 MiniCanvas (opens new window) 并一起扩展它,实现更多功能。
# 8.5.5:小结
本节简单介绍了 Canvas
组件的使用,读者可以掌握使用 Canvas
提供的基础API实现不同的绘制需求,因为 Canvas
的绘制流程比较复杂,笔者介绍了 MiniCanvas (opens new window) 的使用,目前该库还在完善中,非常欢迎大家一起完善它。