写点什么

鸿蒙 HarmonyOS 实战 -ArkUI 组件(Canvas)

作者:蜀道山
  • 2024-05-14
    湖南
  • 本文字数:7372 字

    阅读完需:约 24 分钟

鸿蒙HarmonyOS实战-ArkUI组件(Canvas)

🚀一、Canvas

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


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


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


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


更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY

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

🦋1.1 直接绘制

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


@Entry@Componentstruct 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 来实现。开发者可以通过指定一个离屏渲染的目标缓冲区,然后在这个缓冲区中进行渲染操作,最后再将结果绘制到屏幕上。


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


@Entry@Componentstruct 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 方法。


@Entry@Componentstruct 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 上绘制出来。


@Entry@Componentstruct 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.画布组件常用方法


🦋4.1 基础形状绘制

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


@Entry@Componentstruct 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(绘制描边类文本)等接口进行文本绘制。


@Entry@Componentstruct 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 绘制图片和图像像素信息处理


@Entry@Componentstruct 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 方法用于创建一个径向渐变色。


语法:


createRadialGradient(x0, y0, r0, x1, y1, r1)
复制代码


参数说明:


  • x0:渐变的起始圆的 x 坐标

  • y0:渐变的起始圆的 y 坐标

  • r0:渐变的起始圆的半径

  • x1:渐变的结束圆的 x 坐标

  • y1:渐变的结束圆的 y 坐标

  • r1:渐变的结束圆的半径


@Entry@Componentstruct 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 规则基础形状绘制

@Entry@Componentstruct 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 不规则图形绘制

@Entry@Componentstruct 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%') }}
复制代码


🚀写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

  • 关注小编,同时可以期待后续文章 ing🚀,不定期分享原创知识。

  • 更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY



用户头像

蜀道山

关注

欢迎关注作者公众号:【 蜀道衫】 2023-12-29 加入

3年Java后端,5年Android应用开发,精通Java高并发、JVM调优、以及Android开发各种技能。现专研学习鸿蒙HarmonyOS Next操作系统

评论

发布
暂无评论
鸿蒙HarmonyOS实战-ArkUI组件(Canvas)_鸿蒙_蜀道山_InfoQ写作社区