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    | ![main](./figures/JSMainPage.jpg) | ![Draw Path](figures/JSdrawPath.jpg) | ![Draw Path](figures/JSdrawRect.jpg) | ![Draw Path](figures/JSdrawText.jpg) |
295