# 8.5:Canvas画布组件

ArkUI开发框架提供了 Canvas 画布组件支持我们自绘制各种图形的需求,Canvas 的具体绘制是委托给 CanvasRenderingContext2D 实现的, CanvasRenderingContext2D 提供了一系列绘画相关的方法,笔者把 CanvasRenderingContext2D 简单理解成一个画笔,画笔绘制的内容在画布 Canvas 上显示。本节课主要向读者介绍 CanvasRenderingContext2D 的使用。

# 8.5.1:Canvas定义介绍

interface CanvasInterface {
  (context?: CanvasRenderingContext2D): CanvasAttribute;
}
1
2
3
  • contextCanvas 组件创建的时候需要一个 CanvasRenderingContext2D 实例,该实例负责在 Canvas 上绘制具体内容,比如文本、图片以及各种形状等。

# 8.5.2:Canvas事件介绍

declare class CanvasAttribute extends CommonMethod<CanvasAttribute> {
  onReady(event: () => void): CanvasAttribute;
}
1
2
3
  • onReady()Canvas 组件初始化成功后的回调,绘制相关的操作均在该回调中进行。

简单样例如下所示:

@Entry @Component struct Index {

  // 初始化RenderingContextSettings并设置为抗锯齿
  private setting: RenderingContextSettings = new RenderingContextSettings(true);
  // 初始化CanvasRenderingContext2D
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.setting);

  build() {
    Column() {
      Canvas(this.context)                        // 设置Canvas所需要的context
        .size({width: '100%', height: "100%"})    // 设置Canvas的宽高
        .onReady(() => {                          // 监听回调,在回调内执行绘画操作
          this.context.fillRect(10, 10, 130, 40); // 以(10, 10)为起点坐标,画矩形,默认黑色
        })
    }
    .width('100%')
    .height('100%')
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

样例运行结果如下图所示:

8_5_1_1

# 8.5.3:CanvasRenderingContext2D属性介绍

CanvasRenderingContext2DCanvas 的画笔,继承自 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
}
1
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);
1

MiniCanvas 提供了 drawLine() 方法绘制直线,它接收起始点坐标(startX,startY)和结束点坐标(stopX,stopY)和一个画笔(paint),画笔(paint)支持设置直线的颜色,粗细等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {
  build() {
    Column() {
      MiniCanvas({                                 // 使用MiniCanvas组件
        onDraw: (canvas) => {                      // 在onDraw回调方法内绘制图形
          var 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%"})
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

样例运行结果如下图所示:

8_5_4_1

# 8.5.4.2:绘制文本

public drawText(text: string, x: number, y: number, paint: Paint, maxWidth?: number);
1

MiniCanvas 提供了 drawText() 方法绘制文本, text 是要绘制的文本内容, x 和 y 表示文本绘制的起始坐标,画笔(paint)支持文本的大小,字体,颜色等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          let text = "OpenHarmony";              // 需要绘制的文本
          var paint = new Paint()                // 创建画笔
          paint.setTextSize(vp2px(30))           // 设置字体大小
          canvas.drawText(text, 10, 12, paint);  // 绘制文本

          paint.setColor(Color.Red.toString())   // 设置字体颜色
          canvas.drawText(text, 140, 45, paint); // 绘制文本
        }
      })
    }
    .size({width: '100%', height: "100%"})
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

样例运行结果如下图所示:

8_5_4_2

# 8.5.4.3:绘制圆

public drawCircle(x: number, y: number, radius: number, paint: Paint);
1

MiniCanvas 提供了 drawCircle() 方法绘制圆, x 和 y 表示圆心坐标, radius 表示圆的半径,画笔(paint)支持设置圆的颜色,是否是圆环以及圆环的粗细。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          var 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%"})
  }
}
1
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_3

# 8.5.4.4:绘制椭圆

public drawOval(x: number, y: number, width: number, height: number, paint: Paint);
1

MiniCanvas 提供了 drawOval() 方法绘制椭圆,x和y表示椭圆所在矩形的左上角坐标, width 和 height 表示椭圆所在矩形的宽高,画笔(paint)支持设置圆的颜色,是否是圆环以及圆环的粗细等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          var 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%"})
  }
}
1
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_4

# 8.5.4.5:绘制矩形

public drawRect(x: number, y: number, width: number, height: number, paint: Paint);
1

MiniCanvas 提供了 drawRect() 方法绘制矩形, x 和 y 表示矩形的左上角坐标, width 和 height 表示矩形的宽高,画笔(paint)支持设置矩形的颜色,是否是矩形框以及矩形框的粗细等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          var 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%"})
  }
}
1
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_5

# 8.5.4.6:绘制圆角矩形

public drawRoundRect(x: number, y: number, width: number, height: number, radius: number, paint: Paint);
1

MiniCanvas 提供了 drawRoundRect() 方法绘制圆角矩形, x 和 y 表示圆角矩形的左上角坐标, width 和 height 表示圆角矩形的宽高, radius 表示圆角大小,画笔(paint)支持设置矩形的颜色,是否是矩形框以及矩形框的粗细等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          var 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%"})
  }
}
1
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

# 8.5.4.7:绘制圆弧

drawArc(x: number, y: number, radius: number, startAngle: number, endAngle: number, paint: Paint, counterclockwise?: boolean): void;
1

MiniCanvas 提供了 drawArc() 方法绘制圆弧, x 和 y 表示圆心坐标, radius 表示圆弧的半径, startAngle 表示圆弧起始角度, endAngle 表示圆弧结束角度,画笔(paint)支持设置圆弧的颜色以及是否实心等。简单样例如下所示:

@Entry @Component struct MiniCanvasTest {

  build() {
    Column() {
      MiniCanvas({
        onDraw: (canvas) => {
          var 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%"})
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

样例运行结果如下图所示:

8_5_4_7

# 8.5.4.8:绘制图片

public drawImage(image: ImageBitmap, sx: number, sy: number, sWidth: number, sHeight: number, dx: number, dy: number, dWidth: number, dHeight: number);
1

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) => {
          var image = new ImageBitmap("pages/test.jpeg");	// 创建ImageBitmap实例
          canvas.drawImage(image, 0, 0, 500, 500, 10, 10, 250, 100)// 绘制图片
        }
      })
    }
    .size({width: '100%', height: "100%"})
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

样例运行结果如下图所示:

8_5_4_8

以上就是 MiniCanvas (opens new window) 的简单使用,欢迎读者使用 MiniCanvas (opens new window) 并一起扩展它,实现更多功能。

# 8.5.5:小结

本节简单介绍了 Canvas 组件的使用,读者可以掌握使用 Canvas 提供的基础API实现不同的绘制需求,因为 Canvas 的绘制流程比较复杂,笔者介绍了 MiniCanvas (opens new window) 的使用,目前该库还在完善中,非常欢迎大家一起完善它。

(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2