ArkUI框架之Canvas 画布

Canvas 画布

Canvas提供画布组件,用于自定义绘制图形,开发者使用CanvasRenderingContext2D对象在Canvas组件上进行绘制,绘制对象可以是基础形状、文本、图片等。

1.Canvas 快速入门

onReady(event: () => void)是Canvas组件初始化完成时的事件回调,调用该事件后,可获取Canvas组件的确定宽高,进一步使用CanvasRenderingContext2D对象调用相关API进行图形绘制。

@Entry
  @Component
  struct CanvasDemo {
    //画笔配置对象,true表示开启抗锯齿
    private settings: RenderingContextSettings = new RenderingContextSettings(true)
    //画笔对象,传递画笔配置对象
    private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

    build() {
      Column(){
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .backgroundColor(Color.Pink)
          .onReady(() => {
            this.context.fillStyle = Color.Yellow; 		//设置填充色
            this.context.fillRect(50, 50, 100, 100); 	//填充矩形
          })
      }
      .height('100%')
        .width('100%')
    }
  }

2.常用绘制方法

CanvasRenderingContext2D对象提供了大量的属性和方法,可以用来绘制文本、图形,处理像素等,是Canvas组件的核心。常用接口有fill(对封闭路径进行填充)、clip(设置当前路径为剪切路径)、stroke(进行边框绘制操作)等等,同时提供了fillStyle(指定绘制的填充色)、globalAlpha(设置透明度)与strokeStyle(设置描边的颜色)等属性修改绘制内容的样式。

2.1 绘制矩形

以下是绘制矩形的方法

rect(
  x: number,		//矩形左上角x坐标
  y: number, 		//矩形左上角y坐标
  w: number, 		//矩形宽度
  h: number			//矩形高度
): void

在Canvas画布上绘制一个矩形

b1

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column(){
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //1. 绘制一个矩形,带边框和填充色
          this.context.beginPath()

          //1.1 矩形范围(x坐标,y坐标,宽,高)
          this.context.rect(20,20,200,100)

          //1.2 矩形边框
          this.context.strokeStyle = Color.Black    //边框颜色
          this.context.lineWidth = 2    //边框粗细
          this.context.stroke()         //绘制边框

          //1.3 矩形填充色
          this.context.fillStyle = Color.Yellow
          this.context.fill()
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.2 绘制圆形

以下是绘制圆形的方法

arc(
  x: number, 				//圆心x坐标
  y: number, 				//圆心y坐标
  radius: number, 	//圆的半径
  startAngle: number, 	//开始弧度
  endAngle: number, 		//结束弧度
  counterclockwise?: boolean	//是否逆时针默认false
): void

在Canvas画布上绘制一个圆形

b2

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column(){
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //1. 绘制一个圆形,带边框和填充色
          this.context.beginPath()

          //1.1 圆形范围(圆心x坐标,圆心y坐标,半径,开始弧度,结束弧度)
          this.context.arc(150,150,100,0,Math.PI*2) 

          //1.2 圆形边框
          this.context.strokeStyle = Color.Black    //边框颜色
          this.context.lineWidth = 2    //边框粗细
          this.context.stroke()         //绘制边框

          //1.3 圆形填充色
          this.context.fillStyle = Color.Yellow
          this.context.fill()
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.3 绘制椭圆

绘制椭圆的方法

ellipse(
  x: number, 	//圆心x轴坐标
  y: number, 	//圆心y坐标
  radiusX: number, 	//x轴半径
  radiusY: number, 	//y轴半径
  rotation: number, //椭圆整体旋转的弧度
  startAngle: number,	//起点弧度
  endAngle: number		//终点弧度
): void

b3

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //1. 绘制一个矩形,带边框和填充色
          this.context.beginPath()

          //1.1 椭圆范围(圆心x坐标,圆心y坐标,x轴半径,y轴半径, 旋转弧度, 起始弧度,结束弧度宽)
          this.context.ellipse(150, 150, 120, 80, 0, 0, Math.PI * 2)

          //1.2 矩形边框
          this.context.strokeStyle = Color.Black //边框颜色
          this.context.lineWidth = 2 //边框粗细
          this.context.stroke() //绘制边框

          //1.3 矩形填充色
          this.context.fillStyle = Color.Yellow
          this.context.fill()
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.4 绘制直线

绘制如下图所示的三条直线,确定一条直线至少需要2个端点。

b4

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //1. 创建一条新路径
          this.context.beginPath()
          //1.1 设置线条颜色
          this.context.strokeStyle = Color.Black
          //1.1 设置线条端点样式(butt两端方形)
          this.context.lineCap = "butt"
          //1.2 设置线条宽度(线粗)
          this.context.lineWidth = 8
          //1.3 移动到(20,20)坐标点
          this.context.moveTo(20,20)
          //1.4 连接到 (120,20) 坐标点
          this.context.lineTo(120,20) 
          //1.5 绘制线条
          this.context.stroke()

          //2. 创建一条新路径
          this.context.beginPath()
          //2.1 设置线条端点样式(square两端方形,两端新增长度为宽度线宽度的一半)
          this.context.lineCap = "square"
          this.context.lineWidth = 8
          this.context.moveTo(20,40)
          this.context.lineTo(120,40)
          this.context.stroke()

          //3. 创建一条新路径
          this.context.beginPath()
          //3.1 设置线条端点样式(round线条端点为圆形)
          this.context.lineCap = 'round'
          this.context.lineWidth = 8
          this.context.moveTo(20, 60)
          this.context.lineTo(120, 60)
          this.context.stroke() 
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.5 交点样式

绘制线条时,相交点可以是圆角也可以是尖角。通过this.context.lineJoin 属性设置 设置
● this.context.lineJoin = 'miter' 设置交点为尖叫
● this.context.lineJoin = 'round' 设置交点为圆角

b5

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //1. 绘制多边形
          this.context.beginPath()
          this.context.lineWidth = 8
          this.context.lineJoin = 'miter' //尖角
          this.context.moveTo(20, 20)
          this.context.lineTo(120, 20)
          this.context.lineTo(120, 120)
          this.context.lineTo(20, 120)
          this.context.closePath()
          this.context.stroke()

          //2. 绘制多边形
          this.context.beginPath()
          this.context.lineWidth = 8
          this.context.lineJoin = "round"	//圆角
          this.context.strokeStyle = Color.Red
          this.context.moveTo(70, 20)
          this.context.lineTo(20, 70)
          this.context.lineTo(70, 120)
          this.context.lineTo(120, 70)
          this.context.closePath()
          this.context.stroke()
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.6 绘制文本

在画布上绘制两行文本,一种是填充色文本,一种是描边文本。

b6

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width(300)
        .height(300)
        .backgroundColor(Color.Pink)
        .onReady(() => {
          //绘制填充类文本
          this.context.beginPath()
          this.context.font = '40vp serif'; //大小、字体
          this.context.fillStyle = Color.Yellow
          this.context.fillText("Hello World!", 0, 50);
          this.context.closePath()

          //绘制描边类文本
          this.context.beginPath()
          this.context.font = '30vp serif'  //大小、字体
          this.context.strokeStyle = Color.Red
          this.context.lineWidth = 1
          this.context.strokeText("Hello HarmonyOS NEXT",0,100,300)
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.7 绘制渐变色

在矩形范围内从左到右按照太阳光色谱从红色渐变到紫色

b7

  • 线性渐变
@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width("100%")
        .height("100%")
        .backgroundColor(Color.Pink)
        .onReady(() => {
          const width = this.context.width
          //1. 线性渐变
          //创建一个线性渐变色的CanvasGradient对象
          let grad = this.context.createLinearGradient(0, 0, width, 0)
          //为CanvasGradient对象设置渐变断点值,包括偏移和颜色
          const colors: string[] = [
            "#FF0000", //# 红色
            "#FF4500", //# 橙红色
            "#FFA500", //# 橙色
            "#FFFF00", //# 黄色
            "#90EE90", //# 浅黄绿色(偏向绿色过渡)
            "#00FFFF", //# 青绿色(但在此作为绿色到蓝色的过渡色)
            "#87CEEB", //# 天蓝色
            "#800080", //# 紫色
            "#8B008B", //# 深紫色
            "#4B0082",//# 靛蓝色(偏向紫色)
          ]
          grad.addColorStop(0.0, colors[0]);
          grad.addColorStop(0.1, colors[1]);
          grad.addColorStop(0.2, colors[2]);
          grad.addColorStop(0.3, colors[3]);
          grad.addColorStop(0.4, colors[4]);
          grad.addColorStop(0.5, colors[5]);
          grad.addColorStop(0.6, colors[6]);
          grad.addColorStop(0.8, colors[7]);
          grad.addColorStop(0.9, colors[8]);
          grad.addColorStop(1.0, colors[9]);
          //用CanvasGradient对象填充矩形
          this.context.fillStyle = grad;
          this.context.fillRect(0, 0, width, 100);
        })
    }
    .height("100%")
    .width('100%')
  }
}
  • 径向渐变

b8

createRadialGradient(
  x0: number, 	//起点圆心x坐标
  y0: number,		//起点圆心y坐标
  r0: number, 	//起点圆半径
  x1: number, 	//终点圆心x坐标
  y1: number, 	//终点圆心y坐标
  r1: number		//终点圆半径
): CanvasGradient
@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Canvas(this.context)
        .width("100%")
        .height("100%")
        .backgroundColor(Color.Pink)
        .onReady(() => {
          const width = this.context.width
          //1. 径向渐变
          //创建一个渐变色的CanvasGradient对象
          let grad = this.context.createRadialGradient(150, 150, 30, 150, 150, 150)
          //为CanvasGradient对象设置渐变断点值,包括偏移和颜色
          grad.addColorStop(0.0, '#FF0000');
          grad.addColorStop(0.5, '#FFFFFF');
          grad.addColorStop(1.0, '#BDDB69');
          //用CanvasGradient对象填充矩形
          this.context.fillStyle = grad;
          this.context.fillRect(0, 0, 300, 300);
        })
    }
    .height("100%")
    .width('100%')
  }
}

2.8 绘制图像

如图所示将图像绘制在Canvas画布上;截取屏幕上

@Entry
@Component
struct CanvasDemo {
  //画笔配置对象,true表示开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //画笔对象,传递画笔配置对象
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600)
  private img: ImageBitmap = new ImageBitmap("/images/1234.jpg")

  build() {
    Column() {
      Canvas(this.context)
        .width("100%")
        .height("100%")
        .backgroundColor(Color.Pink)
        .onReady(() => {
          let offContext = this.offCanvas.getContext("2d", this.settings)
          // 使用drawImage接口将图片画在(0,0)为起点,宽高130的区域
          offContext.drawImage(this.img, 0, 0, 150, 150);
          // 使用getImageData接口,获得canvas组件区域中,(50,50)为起点,宽高130范围内的绘制内容
          let imagedata = offContext.getImageData(50, 50, 130, 130);
          // 使用putImageData接口将得到的ImageData画在起点为(150, 150)的区域中
          offContext.putImageData(imagedata, 150, 150); 
          // 将离屏绘制的内容画到canvas组件上
          let image = this.offCanvas.transferToImageBitmap();
          this.context.transferFromImageBitmap(image); 
        })
    }
    .height("100%")
    .width('100%') 
  }
}

鸿蒙学习地址

posted @ 2025-11-14 11:42  leon_teacher  阅读(13)  评论(0)    收藏  举报