1# Using Drawing to Draw and Display Graphics 2 3## When to Use 4 5The @ohos.graphics.drawing module provides basic drawing capabilities, such as drawing rectangles, circles, points, line segments, custom paths, and fonts. 6 7## Available APIs 8 9The table below lists the common APIs provided by the @ohos.graphics.drawing module. For details about all the APIs, see [@ohos.graphics.drawing](../reference/apis-arkgraphics2d/js-apis-graphics-drawing.md). 10 11| API| Description| 12| -------- | -------- | 13| drawPath(path: Path) : void | Draws a custom path.| 14| drawRect(rect: common2D.Rect): void | Draws a rectangle. By default, black is used for filling.| 15| drawTextBlob(blob: TextBlob, x: number, y: number): void | Draws a text blob.| 16| moveTo(x: number, y: number) : void | Sets the start point of a path.| 17| lineTo(x: number, y: number) : void | Draws a line segment from the last point of a path to the target point.| 18| close(): void | Draws a line segment from the current point to the start point of a path.| 19| setAntiAlias(aa: boolean) : void | Enables anti-aliasing for this pen or brush. Anti-aliasing makes the edges of the content smoother.| 20| setColor(color: common2D.Color) : void | Sets a color for this pen or brush.| 21| setStrokeWidth(width: number) : void | Sets a stroke width for this pen.| 22| attachPen(pen: Pen): void | Attaches a pen to a canvas so that the canvas can use the style and color of the pen to outline a shape.| 23| attachBrush(brush: Brush): void | Attaches a brush to a canvas so that the canvas can use the style and color of the brush to fill in a shape.| 24 25## How to Develop 26 27Use the canvas and pen of the @ohos.graphics.drawing module to draw basic 2D graphics and text blobs, and call the drawing and display logic to display them on the screen. 28 29The following walks you through on how to draw and display 2D graphics and text blobs. 30### Adding Dependencies 31 32**Importing Dependency Files** 33```js 34import { FrameNode, NodeController, RenderNode } from '@kit.ArkUI' 35import { common2D, drawing } from '@kit.ArkGraphics2D' 36``` 37 38Now you can use the APIs for drawing. 39 40### Drawing 2D Graphics 41 42Follow the steps below to draw 2D graphics and text blobs by using the canvas and pen of the @ohos.graphics.drawing module. 43 441. **Create a child class of RenderNode.** 45 46 Create the child class **MyRenderNode** and define drawing functions in it. RenderNode contains operations on the tree structure and drawing attributes. The **draw** method called when the RenderNode performs drawing. For details, see [RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md). 47 48 ```js 49 // Create the MyRenderNode class. 50 class MyRenderNode extends RenderNode { 51 52 async draw(context: DrawContext) { 53 // ... 54 } 55 } 56 ``` 57 582. **Construct a path shape.** 59 60 Use **moveTo**, **lineTo**, and **close** of the path to construct a pentagram. 61 62 ```js 63 const canvas = context.canvas 64 let height_ = 1200 65 let width_ = 600 66 let len = height_ / 4 67 let aX = width_ / 2 68 let aY = height_ / 4 69 let dX = aX - len * Math.sin(18.0) 70 let dY = aY + len * Math.cos(18.0) 71 let cX = aX + len * Math.sin(18.0) 72 let cY = dY 73 let bX = aX + (len / 2.0) 74 let bY = aY + Math.sqrt((cX - dX) * (cX - dX) + (len / 2.0) * (len / 2.0)) 75 let eX = aX - (len / 2.0) 76 let eY = bY; 77 78 // Create a path object and use the APIs to construct a pentagram. 79 let path = new drawing.Path() 80 81 // Specify the start point of the path. 82 path.moveTo(aX, aY) 83 84 // Draw a line segment from the last point of a path to the target point. 85 path.lineTo(bX, bY) 86 path.lineTo(cX, cY) 87 path.lineTo(dX, dY) 88 path.lineTo(eX, eY) 89 90 // Close the path. Now the path is drawn. 91 path.close() 92 ``` 93 943. **Set the pen and brush styles.** 95 96 Use **Pen** to create a pen object, and set the attributes such as anti-aliasing, color, and thickness. The pen is used to outline a shape. 97 98 Use **Brush** to create a brush object, and set the brush color. The brush is used to fill in a shape. 99 100 Use **attachPen** and **attachBrush** in canvas to attach the pen and brush to the canvas. 101 102 ```js 103 // Create a pen object and set the anti-aliasing, color, and thickness attributes. 104 let pen = new drawing.Pen() 105 pen.setAntiAlias(true) 106 let pen_color : common2D.Color = { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 } 107 pen.setColor(pen_color) 108 pen.setStrokeWidth(10.0) 109 110 // Attach the pen to the canvas. 111 canvas.attachPen(pen) 112 113 // Create a brush object and set the color. 114 let brush = new drawing.Brush() 115 let brush_color : common2D.Color = { alpha: 0xFF, red: 0x00, green: 0xFF, blue: 0x00 } 116 brush.setColor(brush_color) 117 118 // Attach the brush to the canvas. 119 canvas.attachBrush(brush) 120 ``` 121 1224. **Draw the pentagram.** 123 124 Use **drawPath** in canvas to draw the pentagram on the canvas. 125 126 ```js 127 // Draw the path. 128 canvas.drawPath(path) 129 ``` 130 1315. **Create a MyRenderNode object.** 132 133 Steps 1 to 4 build the **MyRenderNode** class and define the main drawing functions in it. Next, create a **MyRenderNode** object and set its pixel format. 134 135 ```js 136 // Create a MyRenderNode object. 137 const newNode = new MyRenderNode() 138 // Define the pixel format of MyRenderNode. 139 newNode.frame = { x: 100, y: 100, width: 200, height: 800 } 140 newNode.pivot = { x: 0.2, y: 0.8 } 141 newNode.scale = { x: 1, y: 1 } 142 ``` 143 1446. **Draw a rectangle.** 145 146 Use **drawRect** in canvas to draw a rectangle. 147 148 ```js 149 class RectRenderNode extends RenderNode { 150 async draw(context: DrawContext) { 151 const canvas = context.canvas 152 const pen = new drawing.Pen() 153 pen.setStrokeWidth(5) 154 pen.setColor({alpha: 255, red: 255, green: 0, blue: 0}) 155 canvas.attachPen(pen) 156 canvas.drawRect({ left : 200, right : 500, top : 300, bottom : 900}) 157 } 158 } 159 // Create a RectRenderNode object. 160 const rectNode = new RectRenderNode() 161 // Define the pixel format of RectRenderNode. 162 rectNode.frame = { x: 90, y: 100, width: 200, height: 800 } 163 rectNode.pivot = { x: 0.2, y: 0.8 } 164 rectNode.scale = { x: 1, y: 1 } 165 ``` 166 1677. **Draw a text blob.** 168 169 Use **drawTextBlob** in canvas to draw a text blob. 170 171 ```js 172 class TextRenderNode extends RenderNode { 173 async draw(context: DrawContext) { 174 const canvas = context.canvas 175 const brush = new drawing.Brush() 176 brush.setColor({alpha: 255, red: 255, green: 0, blue: 0}) 177 const font = new drawing.Font() 178 font.setSize(100) 179 const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8) 180 canvas.attachBrush(brush) 181 canvas.drawTextBlob(textBlob, 90, 500) 182 } 183 } 184 // Create a TextRenderNode object. 185 const textNode = new TextRenderNode() 186 // Define the pixel format of TextRenderNode. 187 textNode.frame = { x: 90, y: 100, width: 200, height: 800 } 188 textNode.pivot = { x: 0.2, y: 0.8 } 189 textNode.scale = { x: 1, y: 1 } 190 ``` 191 1928. **Create a child class of NodeController.** 193 194 Create the child class **MyNodeController**, and define the functions for creating FrameNode in it. **NodeController** defines the controller of a node container and controls the nodes in the lifecycle of the container. FrameNode defines the basic type of a node and contains a RenderNode. 195 196 ```js 197 class MyNodeController extends NodeController { 198 private rootNode: FrameNode | null = null; 199 200 makeNode(uiContext: UIContext): FrameNode { 201 this.rootNode = new FrameNode(uiContext) 202 if (this.rootNode == null) { 203 return this.rootNode 204 } 205 const renderNode = this.rootNode.getRenderNode() 206 if (renderNode != null) { 207 renderNode.frame = { x: 0, y: 0, width: 10, height: 500 } 208 renderNode.pivot = { x: 50, y: 50 } 209 } 210 return this.rootNode 211 } 212 } 213 ``` 214 2159. **Define an interface for adding a node.** 216 217 Define an interface for adding a RenderNode in the **MyNodeController** class created in step 8. 218 219 ```js 220 addNode(node: RenderNode): void { 221 if (this.rootNode == null) { 222 return 223 } 224 const renderNode = this.rootNode.getRenderNode() 225 if (renderNode != null) { 226 renderNode.appendChild(node) 227 } 228 } 229 ``` 230 23110. **Define an interface for deleting a node.** 232 233 Define an interface for deleting a RenderNode in the **MyNodeController** class created in step 8. 234 235 ```js 236 clearNodes(): void { 237 if (this.rootNode == null) { 238 return 239 } 240 const renderNode = this.rootNode.getRenderNode() 241 if (renderNode != null) { 242 renderNode.clearChildren() 243 } 244 } 245 ``` 246 24711. **Draw the graphics and text blob.** 248 249 Create a **MyNodeController** instance and save it to the NodeContainer, add a **Button** component, and call the defined interfaces. 250 251 ```js 252 @Entry 253 @Component 254 struct RenderTest { 255 private myNodeController: MyNodeController = new MyNodeController() 256 build() { 257 Column() { 258 Row() { 259 NodeContainer(this.myNodeController) 260 .height('100%') 261 Button("Draw Path") 262 .margin({ bottom: 200, right: 12 }) 263 .onClick(() => { 264 this.myNodeController.clearNodes() 265 this.myNodeController.addNode(newNode) 266 }) 267 Button("Draw Rect") 268 .margin({ bottom: 200, right: 12 }) 269 .onClick(() => { 270 this.myNodeController.clearNodes() 271 this.myNodeController.addNode(rectNode) 272 }) 273 Button("Draw Text") 274 .margin({ bottom: 200, right: 12 }) 275 .onClick(() => { 276 this.myNodeController.clearNodes() 277 this.myNodeController.addNode(textNode) 278 }) 279 } 280 .width('100%') 281 .justifyContent(FlexAlign.Center) 282 .shadow(ShadowStyle.OUTER_DEFAULT_SM) 283 .alignItems(VerticalAlign.Bottom) 284 .layoutWeight(1) 285 } 286 } 287 } 288 ``` 289 290 The following figure shows the drawing and display effect. 291 292 | Home page | Pentagram drawn | Rectangle drawn | Text blob drawn | 293 | ------------------------------------ | ----------------------------------------------- | ------------------------------------ | ------------------------------------ | 294 |  |  |  |  | 295