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-->