• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 画布的获取与绘制结果的显示(ArkTS)
2
3
4## 场景介绍
5
6Canvas即画布,提供绘制基本图形的能力,用于在屏幕上绘制图形和处理图形。开发者可以通过Canvas实现自定义的绘图效果,增强应用的用户体验。
7
8
9Canvas是图形绘制的核心,本章中提到的所有绘制操作(包括基本图形的绘制、文字的绘制、图片的绘制、图形变换等)都是基于Canvas的。
10
11
12目前ArkTS有两种获取Canvas的方式:[获取可直接显示的Canvas画布](#获取可直接显示的canvas画布)、[获取离屏的Canvas](#离屏canvas画布的获取与显示),前者在调用绘制接口之后无需进行额外的操作即可完成绘制结果的上屏显示,而后者需要依靠已有的显示手段来显示绘制结果。
13
14
15## 获取可直接显示的Canvas画布
16
17通过[RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md)获取可直接上屏显示的Canvas画布。
18
191. 添加自定义RenderNode。
20
212. 添加自定义[NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md)。
22
233. 重写自定义RenderNode的[draw()](../reference//apis-arkui/js-apis-arkui-renderNode.md#draw)函数,获取Canvas进行自定义的绘制操作,即本章下文中的内容。
24
254. 将自定义NodeController进行显示。
26
27```ts
28import { UIContext, NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI';
29import { drawing } from '@kit.ArkGraphics2D';
30
31// 1. 自定义RenderNode
32export class MyRenderNode extends RenderNode {
33  async draw(context: DrawContext) {
34    const canvas = context.canvas
35    // 3. 自定义的绘制相关操作
36    const brush = new drawing.Brush()
37    brush.setColor({red: 255, blue: 0, green: 0, alpha: 255})
38    canvas.attachBrush(brush)
39    canvas.drawRect({left: 0, right: 300, top: 0, bottom: 300})
40  }
41}
42
43// 2. 自定义NodeController
44export class MyNodeController extends NodeController {
45  private rootNode: FrameNode | null = null;
46  myRenderNode = new MyRenderNode();
47
48  makeNode(uiContext: UIContext): FrameNode {
49    this.rootNode = new FrameNode(uiContext);
50    if (this.rootNode === null) {
51      return this.rootNode
52    }
53
54    const renderNode = this.rootNode.getRenderNode();
55    if (renderNode !== null) {
56      this.myRenderNode.backgroundColor = 0xffffffff;
57      this.myRenderNode.frame = { x: 0, y: 0, width: 4800, height: 4800 };
58      this.myRenderNode.pivot = { x: 0.2, y: 0.8 }
59      this.myRenderNode.scale = { x: 1, y: 1 }
60      renderNode.appendChild(this.myRenderNode);
61      renderNode.clipToFrame = true
62    }
63    return this.rootNode;
64  }
65}
66
67@Entry
68@Component
69struct RenderTest {
70  @State message: string = 'hello'
71  build() {
72    Row() {
73      Column() {
74        // 4. 将自定义NodeController进行显示
75        NodeContainer(new MyNodeController())
76          .width('100%')
77      }
78      .width('100%')
79      .height('80%')
80    }
81    .height('100%')
82  }
83}
84```
85
86
87## 离屏Canvas画布的获取与显示
88
891. 添加自定义RenderNode。
90
912. 添加自定义[NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md)。
92
933. 在MyNodeController的aboutToAppear()函数中创建PixeMap。
94
954. 重写自定义RenderNode的[draw()](../reference//apis-arkui/js-apis-arkui-renderNode.md#draw)函数,在其中获取离屏Canvas进行绘制:
96
97   1. 利用3中创建的PixelMap构造离屏Canvas。
98   2. 对离屏Canvas进行自定义的绘制操作。
99   3. 将离屏Canvas的绘制结果交给RenderNode。
100
1015. 将自定义NodeController进行显示。
102
103```ts
104import { UIContext, NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI';
105import { image } from '@kit.ImageKit';
106import { taskpool } from '@kit.ArkTS';
107import { drawing } from '@kit.ArkGraphics2D';
108
109// 1. 自定义RenderNode
110export class MyRenderNode extends RenderNode {
111  pixelMap: image.PixelMap | null = null;
112  setPixelMap(pixelMap: image.PixelMap) {
113    this.pixelMap = pixelMap
114  }
115
116  async draw(context: DrawContext) {
117    const canvas = context.canvas
118    if (this.pixelMap != null) {
119      // 4.1 利用3中创建的PixelMap构造离屏Canvas
120      const canvas_ = new drawing.Canvas(this.pixelMap);
121
122      // 4.2 离屏绘制
123      const brush = new drawing.Brush();
124      brush.setColor({ alpha: 255, red: 255, green: 0, blue: 0 });
125      canvas_.attachBrush(brush);
126      canvas_.drawRect({left:0,right:100,top:0,bottom:100});
127
128      // 4.3 将离屏Canvas的绘制结果交给RenderNode
129      canvas.drawImage(this.pixelMap, 0, 0);
130    }
131  }
132}
133
134@Concurrent
135async function CreatePixelMapAsync() {
136  const color : ArrayBuffer = new ArrayBuffer(40000);  // 40000为需要创建的像素buffer大小,取值为:height * width *4
137  let opts : image.InitializationOptions = { editable: true, pixelFormat: 3, size: { height: 100, width: 100 } }
138  const pixel = await image.createPixelMap(color, opts);
139  return pixel;
140}
141
142// 2. 自定义NodeController
143export class MyNodeController extends NodeController {
144  private rootNode: FrameNode | null = null;
145  myRenderNode = new MyRenderNode();
146
147  // 3. 在MyNodeController的aboutToAppear中创建PixeMap
148  aboutToAppear(): void {
149    let task = new taskpool.Task(CreatePixelMapAsync);
150    taskpool.execute(task).then((pixel:Object)=>{
151      this.myRenderNode.setPixelMap(pixel as image.PixelMap)
152      this.myRenderNode.invalidate()
153    })
154  }
155
156  makeNode(uiContext: UIContext): FrameNode {
157    this.rootNode = new FrameNode(uiContext);
158    if (this.rootNode === null) {
159      return this.rootNode
160    }
161
162    const renderNode = this.rootNode.getRenderNode();
163    if (renderNode !== null) {
164      this.myRenderNode.backgroundColor = 0xffffffff;
165      this.myRenderNode.frame = { x: 0, y: 0, width: 4800, height: 4800 };
166      this.myRenderNode.pivot = { x: 0.2, y: 0.8 }
167      this.myRenderNode.scale = { x: 1, y: 1 }
168      renderNode.appendChild(this.myRenderNode);
169      renderNode.clipToFrame = true
170    }
171    return this.rootNode;
172  }
173}
174
175
176@Entry
177@Component
178struct RenderTest {
179  @State message: string = 'hello'
180  nodeController = new MyNodeController()
181
182  build() {
183    Row() {
184      Column() {
185        // 5. 将自定义NodeController进行显示
186        NodeContainer(this.nodeController)
187          .width('100%')
188      }
189      .width('100%')
190      .height('80%')
191    }
192    .height('100%')
193  }
194}
195```
196
197<!--RP1-->
198## 相关实例
199
200针对Drawing(ArkTS)的开发,有以下相关实例可供参考:
201
202- [ArkTSGraphicsDraw (API14)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/DocsSample/Drawing/ArkTSGraphicsDraw)
203<!--RP1End-->