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