经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » 鸿蒙 » 查看文章
鸿蒙HarmonyOS实战-ArkUI组件(Canvas)
来源:cnblogs  作者:蜀道山QAQ  时间:2024/4/19 8:56:11  对本文有异议

??一、Canvas

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

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

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

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

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

??1.1 直接绘制

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

  1. @Entry
  2. @Component
  3. struct CanvasExample1 {
  4. //用来配置CanvasRenderingContext2D对象的参数,包括是否开启抗锯齿,true表明开启抗锯齿。
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. //用来创建CanvasRenderingContext2D对象,通过在canvas中调用CanvasRenderingContext2D对象来绘制。
  7. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  8. build() {
  9. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  10. //在canvas中调用CanvasRenderingContext2D对象。
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() => {
  16. //可以在这里绘制内容。
  17. this.context.strokeRect(50, 50, 200, 150);
  18. })
  19. }
  20. .width('100%')
  21. .height('100%')
  22. }
  23. }

image

??1.2 离屏绘制

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

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

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

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

  1. @Entry
  2. @Component
  3. struct CanvasExample2 {
  4. //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  7. //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  8. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  9. build() {
  10. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() =>{
  16. //可以在这里绘制内容
  17. this.offContext.strokeRect(50, 50, 200, 150);
  18. //将离屏绘值渲染的图像在普通画布上显示
  19. let image = this.offContext.transferToImageBitmap();
  20. this.context.transferFromImageBitmap(image);
  21. })
  22. }
  23. .width('100%')
  24. .height('100%')
  25. }
  26. }

image

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

??2.初始化画布组件

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

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

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

  1. @Entry
  2. @Component
  3. struct CanvasExample2 {
  4. //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  7. //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  8. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  9. build() {
  10. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() => {
  16. this.context.fillStyle = '#0097D4';
  17. this.context.fillRect(50, 50, 100, 100);
  18. })
  19. }
  20. .width('100%')
  21. .height('100%')
  22. }
  23. }

image

??3.画布组件绘制方式

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

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

  1. @Entry
  2. @Component
  3. struct CanvasExample2 {
  4. //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  7. //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  8. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  9. build() {
  10. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() =>{
  16. this.context.beginPath();
  17. this.context.moveTo(50, 50);
  18. this.context.lineTo(280, 160);
  19. this.context.stroke();
  20. })
  21. Canvas(this.context)
  22. .width('100%')
  23. .height('100%')
  24. .backgroundColor('#F5DC62')
  25. .onReady(() =>{
  26. let region = new Path2D();
  27. region.arc(100, 75, 50, 0, 6.28);
  28. this.context.stroke(region);
  29. })
  30. }
  31. .width('100%')
  32. .height('100%')
  33. }
  34. }

image

??4.画布组件常用方法

image
image

??4.1 基础形状绘制

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

  1. @Entry
  2. @Component
  3. struct CanvasExample2 {
  4. //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  7. //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  8. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  9. build() {
  10. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() =>{
  16. //绘制矩形
  17. this.context.beginPath();
  18. this.context.rect(100, 50, 100, 100);
  19. this.context.stroke();
  20. //绘制圆形
  21. this.context.beginPath();
  22. this.context.arc(150, 250, 50, 0, 6.28);
  23. this.context.stroke();
  24. //绘制椭圆
  25. this.context.beginPath();
  26. this.context.ellipse(150, 450, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2);
  27. this.context.stroke();
  28. })
  29. }
  30. .width('100%')
  31. .height('100%')
  32. }
  33. }

image

??4.2 文本绘制

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

  1. @Entry
  2. @Component
  3. struct CanvasExample2 {
  4. //用来配置CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象的参数,包括是否开启抗锯齿。true表明开启抗锯齿
  5. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  6. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  7. //用来创建OffscreenCanvasRenderingContext2D对象,width为离屏画布的宽度,height为离屏画布的高度。通过在canvas中调用OffscreenCanvasRenderingContext2D对象来绘制。
  8. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  9. build() {
  10. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  11. Canvas(this.context)
  12. .width('100%')
  13. .height('100%')
  14. .backgroundColor('#F5DC62')
  15. .onReady(() =>{
  16. //绘制填充类文本
  17. this.context.font = '50px sans-serif';
  18. this.context.fillText("Hello World!", 50, 100);
  19. //绘制描边类文本
  20. this.context.font = '55px sans-serif';
  21. this.context.strokeText("Hello World!", 50, 150);
  22. })
  23. }
  24. .width('100%')
  25. .height('100%')
  26. }
  27. }

image

??4.3 绘制图片和图像像素信息处理

image

  1. @Entry
  2. @Component
  3. struct GetImageData {
  4. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  5. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  6. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  7. private img:ImageBitmap = new ImageBitmap("1702344909275.jpg")
  8. build() {
  9. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  10. Canvas(this.context)
  11. .width('100%')
  12. .height('100%')
  13. .backgroundColor('#F5DC62')
  14. .onReady(() =>{
  15. // 使用drawImage接口将图片画在(0,0)为起点,宽高130的区域
  16. this.offContext.drawImage(this.img,0,0,130,130);
  17. // 使用getImageData接口,获得canvas组件区域中,(50,50)为起点,宽高130范围内的绘制内容
  18. let imagedata = this.offContext.getImageData(50,50,130,130);
  19. // 使用putImageData接口将得到的ImageData画在起点为(150, 150)的区域中
  20. this.offContext.putImageData(imagedata,150,150);
  21. // 将离屏绘制的内容画到canvas组件上
  22. let image = this.offContext.transferToImageBitmap();
  23. this.context.transferFromImageBitmap(image);
  24. })
  25. }
  26. .width('100%')
  27. .height('100%')
  28. }
  29. }

image

??4.4 其他方法

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

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

语法:

  1. createRadialGradient(x0, y0, r0, x1, y1, r1)

参数说明:

  • x0:渐变的起始圆的x坐标
  • y0:渐变的起始圆的y坐标
  • r0:渐变的起始圆的半径
  • x1:渐变的结束圆的x坐标
  • y1:渐变的结束圆的y坐标
  • r1:渐变的结束圆的半径
  1. @Entry
  2. @Component
  3. struct GetImageData {
  4. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  5. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  6. private offContext: OffscreenCanvasRenderingContext2D = new OffscreenCanvasRenderingContext2D(600, 600, this.settings)
  7. private img:ImageBitmap = new ImageBitmap("1702344909275.jpg")
  8. build() {
  9. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  10. Canvas(this.context)
  11. .width('100%')
  12. .height('100%')
  13. .backgroundColor('#F5DC62')
  14. .onReady(() =>{
  15. //创建一个径向渐变色的CanvasGradient对象
  16. let grad = this.context.createRadialGradient(200,200,50, 200,200,200)
  17. //为CanvasGradient对象设置渐变断点值,包括偏移和颜色
  18. grad.addColorStop(0.0, '#E87361');
  19. grad.addColorStop(0.5, '#FFFFF0');
  20. grad.addColorStop(1.0, '#BDDB69');
  21. //用CanvasGradient对象填充矩形
  22. this.context.fillStyle = grad;
  23. this.context.fillRect(0, 0, 400, 400);
  24. })
  25. }
  26. .width('100%')
  27. .height('100%')
  28. }
  29. }

image

??5.场景示例

??5.1 规则基础形状绘制

  1. @Entry
  2. @Component
  3. struct ClearRect {
  4. private settings: RenderingContextSettings = new RenderingContextSettings(true);
  5. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  6. build() {
  7. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  8. Canvas(this.context)
  9. .width('100%')
  10. .height('100%')
  11. .backgroundColor('#F5DC62')
  12. .onReady(() =>{
  13. // 设定填充样式,填充颜色设为蓝色
  14. this.context.fillStyle = '#0097D4';
  15. // 以(50, 50)为左上顶点,画一个宽高200的矩形
  16. this.context.fillRect(50,50,200,200);
  17. // 以(70, 70)为左上顶点,清除宽150高100的区域
  18. this.context.clearRect(70,70,150,100);
  19. })
  20. }
  21. .width('100%')
  22. .height('100%')
  23. }
  24. }

image

??5.2 不规则图形绘制

  1. @Entry
  2. @Component
  3. struct Path2d {
  4. private settings: RenderingContextSettings = new RenderingContextSettings(true);
  5. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  6. build() {
  7. Row() {
  8. Column() {
  9. Canvas(this.context)
  10. .width('100%')
  11. .height('100%')
  12. .backgroundColor('#F5DC62')
  13. .onReady(() =>{
  14. // 使用Path2D的接口构造一个五边形
  15. let path = new Path2D();
  16. path.moveTo(150, 50);
  17. path.lineTo(50, 150);
  18. path.lineTo(100, 250);
  19. path.lineTo(200, 250);
  20. path.lineTo(250, 150);
  21. path.closePath();
  22. // 设定填充色为蓝色
  23. this.context.fillStyle = '#0097D4';
  24. // 使用填充的方式,将Path2D描述的五边形绘制在canvas组件内部
  25. this.context.fill(path);
  26. })
  27. }
  28. .width('100%')
  29. }
  30. .height('100%')
  31. }
  32. }

image

??写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing??,不定期分享原创知识。
  • 更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY
    image

原文链接:https://www.cnblogs.com/shudaoshan/p/18144341

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号