首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】2023年12月 HarmonyOS教学课程 029-ArkUI组件(Canvas)

【愚公系列】2023年12月 HarmonyOS教学课程 029-ArkUI组件(Canvas)

作者头像
愚公搬代码
发布2025-06-02 16:46:10
发布2025-06-02 16:46:10
13600
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行

🚀一、Canvas

Canvas组件是一种图形渲染组件,它提供了一个画布(canvas),开发者可以在上面绘制各种图形、文本等。Canvas组件通常用于创建游戏、数据可视化等需要动态绘制图形的应用程序。

Canvas组件提供了多个API,开发者可以使用这些API进行绘制操作。常用的API包括绘制矩形、圆形、线条、文字等。开发者可以设置画布的大小、背景色、绘制的颜色、线条的宽度等属性。

在Canvas组件中,开发者可以监听鼠标事件(如点击、移动等)和键盘事件,以便根据用户的交互来实现相应的操作。

Canvas组件的使用通常需要一定的编程知识和技巧,开发者需要了解如何使用API进行绘图操作,以及如何处理用户的交互事件。

🔎1.使用画布组件绘制自定义图形

🦋1.1 直接绘制

Canvas直接绘制图形的原理是通过Canvas API调用一系列绘制方法来在Canvas元素上绘制图形和图像。Canvas元素本身是一个空的矩形区域,通过获取Canvas的上下文(context),可以使用上下文提供的绘制方法来进行绘制。

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample1 {
  //用来配置CanvasRenderingContext2D对象的参数,包括是否开启抗锯齿,true表明开启抗锯齿。
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //用来创建CanvasRenderingContext2D对象,通过在canvas中调用CanvasRenderingContext2D对象来绘制。
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      //在canvas中调用CanvasRenderingContext2D对象。
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() => {
          //可以在这里绘制内容。
          this.context.strokeRect(50, 50, 200, 150);
        })
    }
    .width('100%')
    .height('100%')
  }
}
🦋1.2 离屏绘制

离屏绘制(offscreen rendering)是指将渲染结果绘制到与屏幕不直接相关的缓冲区中进行处理。传统的渲染方式是直接将图像渲染到屏幕上,而离屏绘制则是在一个特定的缓冲区中进行渲染,然后再将渲染结果显示到屏幕上。

离屏绘制的主要作用是实现一些特殊效果,比如阴影、模糊、遮罩等。这些效果通常需要在渲染过程中进行多次操作,直接在屏幕上渲染会导致效率低下。使用离屏绘制可以在一个独立的缓冲区中进行这些操作,然后再将结果绘制到屏幕上。

离屏绘制可以通过一些图形库或引擎来实现,例如OpenGL、DirectX等。在移动设备上,离屏绘制通常使用Frame Buffer来实现。开发者可以通过指定一个离屏渲染的目标缓冲区,然后在这个缓冲区中进行渲染操作,最后再将结果绘制到屏幕上。

离屏绘制虽然可以实现一些特殊效果,但由于需要额外的资源和计算开销,使用不当会导致性能问题。因此,在使用离屏绘制时应该注意减少不必要的操作和资源消耗,以提高性能和用户体验。

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample2 {
  //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          //可以在这里绘制内容
          this.offContext.strokeRect(50, 50, 200, 150);
          //将离屏绘值渲染的图像在普通画布上显示
          let image = this.offContext.transferToImageBitmap();
          this.context.transferFromImageBitmap(image);
        })
    }
    .width('100%')
    .height('100%')
  }
}

在Canvas上加载Lottie动画时,需要先按照如下方式下载Lottie,具体使用:https://ohpm.openharmony.cn/#/cn/detail/@ohos/lottie

🔎2.初始化画布组件

在HarmonyOS中,Canvas类是用于绘制图形的核心类。Canvas类提供了onReady方法,用于在Canvas准备好进行绘制之后的回调操作。

当Canvas准备好进行绘制时,会调用onReady方法。开发者可以重写onReady方法,实现一些绘制前的准备工作,例如设置画笔颜色、绘制区域等。

要使用Canvas的onReady方法,需要创建一个Canvas实例,然后通过实例调用onReady方法。

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample2 {
  //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() => {
          this.context.fillStyle = '#0097D4';
          this.context.fillRect(50, 50, 100, 100);
        })
    }
    .width('100%')
    .height('100%')
  }
}

🔎3.画布组件绘制方式

Canvas类支持使用Path2D对象来绘制复杂的路径图形。

Path2D是一个可重用的路径对象,用于描述二维空间中的路径。开发者可以使用Path2D对象来定义路径的轮廓,并在Canvas上绘制出来。

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample2 {
  //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          this.context.beginPath();
          this.context.moveTo(50, 50);
          this.context.lineTo(280, 160);
          this.context.stroke();
        })
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          let region = new Path2D();
          region.arc(100, 75, 50, 0, 6.28);
          this.context.stroke(region);
        })
    }
    .width('100%')
    .height('100%')
  }
}

🔎4.画布组件常用方法

方法/属性

说明

fill()

对封闭路径进行填充

clip()

设置当前路径为剪切路径

stroke()

进行边框绘制操作

fillStyle

指定绘制的填充色

globalAlpha

设置透明度

strokeStyle

设置描边的颜色

Font

设置字体样式

textAlign

设置文本对齐方式

textBaseline

设置基线对齐方式

measureText()

测量文本的宽度

drawImage()

绘制图片

createImageData()

创建一个新的、空白的ImageData对象

getImageData()

获取指定区域的图像数据

putImageData()

将像素数据放回画布上的指定位置

createLinearGradient()

创建线性渐变

createRadialGradient()

创建径向渐变

createPattern()

创建图案

drawFocusIfNeeded()

如果元素具有焦点,则绘制它

addHitRegion()

添加点击区域

removeHitRegion()

移除点击区域

isPointInPath()

判断指定点是否在路径中

clearRect()

清除指定矩形区域

save()

保存当前绘图状态

restore()

恢复上一个保存的绘图状态

scale()

缩放当前绘图

rotate()

旋转当前绘图

translate()

平移当前绘图

transform()

通过矩阵变换,应用缩放、旋转、平移、扭曲等变换

setTransform()

通过矩阵变换,应用缩放、旋转、平移等变换

createOffscreenCanvas()

创建离屏画布

getContext()

获取绘图上下文对象

draw()

将离屏画布上的绘制内容绘制到主画布上

clear()

清除离屏画布

closePath()

关闭当前路径

moveTo()

将绘图游标移动到指定的坐标位置

lineTo()

添加一条直线连接到指定的坐标点

arc()

以给定的中心点和半径,绘制弧形路径

quadraticCurveTo()

添加二次贝塞尔曲线连接到指定的坐标点

bezierCurveTo()

添加三次贝塞尔曲线连接到指定的坐标点

arcTo()

通过给定的控制点和半径,绘制连接两个切线的圆弧路径

rect()

绘制一个矩形路径

isPointInStroke()

判断指定点是否在路径的描边上

strokeRect()

绘制一个矩形路径的边框

fillRect()

绘制一个填充的矩形路径

beginPath()

开始一个新的路径

drawTextOnPath()

沿着路径绘制文本

drawVisible()

绘制离屏画布的可见区域到主画布上

toDataURL()

将画布内容转为数据URL格式

getTransform()

获取当前绘图的变换矩阵

setLineDash()

设置虚线样式

getLineDash()

获取虚线样式

resetTransform()

重置当前绘图的变换矩阵

drawCustomEffect()

绘制自定义特效

drawShadow()

绘制阴影

🦋4.1 基础形状绘制

可以通过arc(绘制弧线路径)、 ellipse(绘制一个椭圆)、rect(创建矩形路径)等接口绘制基础形状

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample2 {
  //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          //绘制矩形
          this.context.beginPath();
          this.context.rect(100, 50, 100, 100);
          this.context.stroke();
          //绘制圆形
          this.context.beginPath();
          this.context.arc(150, 250, 50, 0, 6.28);
          this.context.stroke();
          //绘制椭圆
          this.context.beginPath();
          this.context.ellipse(150, 450, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2);
          this.context.stroke();
        })
    }
    .width('100%')
    .height('100%')
  }
}
🦋4.2 文本绘制

可以通过fillText(绘制填充类文本)、strokeText(绘制描边类文本)等接口进行文本绘制。

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct CanvasExample2 {
  //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          //绘制填充类文本
          this.context.font = '50px sans-serif';
          this.context.fillText("Hello World!", 50, 100);
          //绘制描边类文本
          this.context.font = '55px sans-serif';
          this.context.strokeText("Hello World!", 50, 150);
        })
    }
    .width('100%')
    .height('100%')
  }
}
🦋4.3 绘制图片和图像像素信息处理

接口

描述

drawImage

用于绘制图像

putImageData

使用ImageData数据填充新的矩形区域

createImageData

创建新的ImageData对象

getPixelMap

以当前canvas指定区域内的像素创建PixelMap对象

getImageData

以当前canvas指定区域内的像素创建ImageData对象

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct GetImageData {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  private img:ImageBitmap = new ImageBitmap("1702344909275.jpg")

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          // 使用drawImage接口将图片画在(0,0)为起点,宽高130的区域
          this.offContext.drawImage(this.img,0,0,130,130);
          // 使用getImageData接口,获得canvas组件区域中,(50,50)为起点,宽高130范围内的绘制内容
          let imagedata = this.offContext.getImageData(50,50,130,130);
          // 使用putImageData接口将得到的ImageData画在起点为(150, 150)的区域中
          this.offContext.putImageData(imagedata,150,150);
          // 将离屏绘制的内容画到canvas组件上
          let image = this.offContext.transferToImageBitmap();
          this.context.transferFromImageBitmap(image);
        })
    }
    .width('100%')
    .height('100%')
  }
}
🦋4.4 其他方法

Canvas中还提供其他类型的方法。渐变(CanvasGradient对象)相关的方法:createLinearGradient(创建一个线性渐变色)、createRadialGradient(创建一个径向渐变色)等。

Canvas的createRadialGradient方法用于创建一个径向渐变色。

语法:

代码语言:javascript
代码运行次数:0
运行
复制
createRadialGradient(x0, y0, r0, x1, y1, r1)

参数说明:

  • x0:渐变的起始圆的x坐标
  • y0:渐变的起始圆的y坐标
  • r0:渐变的起始圆的半径
  • x1:渐变的结束圆的x坐标
  • y1:渐变的结束圆的y坐标
  • r1:渐变的结束圆的半径
代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct GetImageData {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  private img:ImageBitmap = new ImageBitmap("1702344909275.jpg")

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          //创建一个径向渐变色的CanvasGradient对象
          let grad = this.context.createRadialGradient(200,200,50, 200,200,200)
          //为CanvasGradient对象设置渐变断点值,包括偏移和颜色
          grad.addColorStop(0.0, '#E87361');
          grad.addColorStop(0.5, '#FFFFF0');
          grad.addColorStop(1.0, '#BDDB69');
          //用CanvasGradient对象填充矩形
          this.context.fillStyle = grad;
          this.context.fillRect(0, 0, 400, 400);
        })
    }
    .width('100%')
    .height('100%')
  }
}

🔎5.场景示例

🦋5.1 规则基础形状绘制
代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct ClearRect {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() =>{
          // 设定填充样式,填充颜色设为蓝色
          this.context.fillStyle = '#0097D4';
          // 以(50, 50)为左上顶点,画一个宽高200的矩形
          this.context.fillRect(50,50,200,200);
          // 以(70, 70)为左上顶点,清除宽150高100的区域
          this.context.clearRect(70,70,150,100);
        })
    }
    .width('100%')
    .height('100%')
  }
}
🦋5.2 不规则图形绘制
代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@Component
struct Path2d {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  build() {
    Row() {
      Column() {
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .backgroundColor('#F5DC62')
          .onReady(() =>{
            // 使用Path2D的接口构造一个五边形
            let path = new Path2D();
            path.moveTo(150, 50);
            path.lineTo(50, 150);
            path.lineTo(100, 250);
            path.lineTo(200, 250);
            path.lineTo(250, 150);
            path.closePath();
            // 设定填充色为蓝色
            this.context.fillStyle = '#0097D4';
            // 使用填充的方式,将Path2D描述的五边形绘制在canvas组件内部
            this.context.fill(path);
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🚀一、Canvas
    • 🔎1.使用画布组件绘制自定义图形
      • 🦋1.1 直接绘制
      • 🦋1.2 离屏绘制
    • 🔎2.初始化画布组件
    • 🔎3.画布组件绘制方式
    • 🔎4.画布组件常用方法
      • 🦋4.1 基础形状绘制
      • 🦋4.2 文本绘制
      • 🦋4.3 绘制图片和图像像素信息处理
      • 🦋4.4 其他方法
    • 🔎5.场景示例
      • 🦋5.1 规则基础形状绘制
      • 🦋5.2 不规则图形绘制
  • 🚀感谢:给读者的一封信
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档