# 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 组件初始化成功后的回调,绘制相关的操作均在该回调中进行。

简单样例如下所示:

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

    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回调方法内绘制图形
              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%"})
      }
    }
    
    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";              // 需要绘制的文本
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    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) => {
              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%"})
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

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

    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

    中央网信办互联网违法和不良信息举报中心

    天津市互联网违法和不良信息举报中心