• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using the Drawing Feature
2
3The drawing feature is provided by the drawing component in the framework, with support for the SVG standard drawing commands.
4
5This section describes how to use the drawing component to draw food composition labels (basic geometric shapes) and apply logos (custom graphics) on the details page.
6
7## Drawing Basic Geometric Shapes
8
9The drawing component encapsulates some common basic geometric shapes, such as rectangles, circles, and ellipses, eliminating the need to calculate routes.
10
11In the food component table on the **FoodDetail** page, each food group is labeled with a round icon.
12
131. Create a **Circle** component and add a round icon before each food group as a label. Set the circle diameter to 6vp. Modify the **IngredientItem** method in the **ContentTable** component on the **FoodDetail** page by adding **Circle** before the food group name.
14
15   ```ts
16   // FoodDetail.ets
17   @Component
18   struct ContentTable {
19     private foodItem: FoodData
20
21     @Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {
22       Flex() {
23         Text(title)
24           .fontSize(17.4)
25           .fontWeight(FontWeight.Bold)
26           .layoutWeight(1)
27         Flex({ alignItems: ItemAlign.Center }) {
28           Circle({width: 6, height: 6})
29             .margin({right: 12})
30             .fill(colorValue)
31           Text(name)
32             .fontSize(17.4)
33             .flexGrow(1)
34           Text(value)
35             .fontSize(17.4)
36         }
37         .layoutWeight(2)
38       }
39     }
40
41     build() {
42       ......
43     }
44   }
45   ```
46
472. To use different label colors for different food groups, call **IngredientItem** in the **build** method to fill the circles with different colors.
48
49   ```ts
50   // FoodDetail.ets
51   @Component
52   struct ContentTable {
53     private foodItem: FoodData
54
55     @Builder IngredientItem(title:string, colorValue: string, name: string, value: string) {
56       Flex() {
57         Text(title)
58           .fontSize(17.4)
59           .fontWeight(FontWeight.Bold)
60           .layoutWeight(1)
61         Flex({ alignItems: ItemAlign.Center }) {
62           Circle({width: 6, height: 6})
63             .margin({right: 12})
64             .fill(colorValue)
65           Text(name)
66             .fontSize(17.4)
67             .flexGrow(1)
68           Text(value)
69             .fontSize(17.4)
70         }
71         .layoutWeight(2)
72       }
73     }
74
75     build() {
76       Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {
77         this.IngredientItem('Calories', '#FFf54040', 'Calories', this.foodItem.calories + 'kcal')
78         this.IngredientItem('Nutrition', '#FFcccccc', 'Protein', this.foodItem.protein + 'g')
79         this.IngredientItem(' ', '#FFf5d640', 'Fat', this.foodItem.fat + 'g')
80         this.IngredientItem(' ', '#FF9e9eff', 'Carbohydrates', this.foodItem.carbohydrates + 'g')
81         this.IngredientItem(' ', '#FF53f540', 'VitaminC', this.foodItem.vitaminC + 'mg')
82       }
83       .height(280)
84       .padding({ top: 30, right: 30, left: 30 })
85     }
86   }
87   ```
88
89   ![drawing-feature](figures/drawing-feature.png)
90
91## Drawing Custom Graphs
92
93In addition to drawing basic geometric shapes, you can also use the **\<Path>** component to draw a custom path. The following describes how to draw an application logo.
94
951. Create the page **Logo.ets** in the **pages** folder.
96
97   ![drawing-feature1](figures/drawing-feature1.png)
98
992. Delete the template code from **Logo.ets** and create a logo component.
100
101   ```ts
102   @Entry
103   @Component
104   struct Logo {
105     build() {
106     }
107   }
108   ```
109
1103. Create a **\<Flex>** component as the root node, set the width and height to 100%, set the alignment mode on the main axis and cross axis to **Center**, and create a **\<Shape>** component as a child component of **\<Flex>**.
111
112   The **\<Shape>** component is the parent component of all drawing components. To combine multiple drawing components into a whole, create a **\<Shape>** as their parent component.
113
114   Draw a logo with the size of 630 px x 630 px. The declarative development paradigm supports multiple length units. In the preceding sections, **number** is used as a parameter, which means that the default length unit – virtual pixel (vp) is used. The virtual pixel count is related to the device resolution and screen density. For example, if the device resolution is 1176 x 2400 and the reference screen resolution is 3, with the formula of vp = px/resolution, the width of the device screen is 392 vp.
115
116   The drawing components follow the SVG standard and use px as the unit by default. Therefore, to facilitate consistency, px is also used as the unit of the logo. The declarative development framework also supports the px unit, with the input parameter of the string type. For example, to set the width to 630px (210vp), use **width('*630px*')** or **width(*210*)**.
117
118   ```ts
119   @Entry
120   @Component
121   struct Logo {
122     build() {
123       Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
124         Shape() {
125
126         }
127         .height('630px')
128         .width('630px')
129       }
130       .width('100%')
131       .height('100%')
132     }
133   }
134   ```
135
1364. Fill the page with gradient colors. Set the gradient mode to linear gradient, the offset angle to 180 degrees, and the color stops to #BDE895 -> 95DE7F -> #7AB967 in the ranges of [0, 0.1], (0.1, 0.6], and (0.6, 1], respectively.
137
138   ```ts
139   .linearGradient(
140     {
141       angle: 180,
142       colors: [['#BDE895', 0.1], ["#95DE7F", 0.6],  ["#7AB967", 1]]
143   })
144   ```
145
146   ![drawing-feature2](figures/drawing-feature2.png)
147
148   ```ts
149   @Entry
150   @Component
151   struct Logo {
152     build() {
153       Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
154         Shape() {
155
156         }
157         .height('630px')
158         .width('630px')
159       }
160       .width('100%')
161       .height('100%')
162       .linearGradient(
163       {
164         angle: 180,
165         colors: [['#BDE895', 0.1], ["#95DE7F", 0.6],  ["#7AB967", 1]]
166       })
167     }
168   }
169   ```
170
171   ![drawing-feature3](figures/drawing-feature3.png)
172
1735. Set the drawing command to draw the first path.
174
175   ```ts
176   Path()
177     .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
178   ```
179
180   The **Path** drawing commands comply with the SVG standard. The preceding command can be divided into the following:
181
182   ```ts
183   M162 128.7
184   ```
185
186   Start a new subpath at point (162, 128.7).
187
188   ```ts
189   a222 222 0 0 1 100.8 374.4
190   ```
191
192   Draw an elliptical arc, setting **rx** and **ry** to **222**, **x-axis-rotation** to **0**, **large-arc-flag** to **0**, and **sweep-flag** to **1** (which means to draw the arc counterclockwise). The lowercase **a** indicates a relative position. In this example, the end point coordinate is (162 + 100.8 = 262.8, 128.7 + 374.4 = 503.1).
193
194   ```ts
195   H198
196   ```
197
198   Draw a horizontal line from point (262.8, 503.1) to point (198, 503.1).
199
200   ```ts
201   a36 36 0 0 3 -36 -36
202   ```
203
204   Draw a circular arc. The input parameters are the same as those in drawing an elliptical arc. The end point is (198 - 36 = 162, 503.1 - 36 = 467.1).
205
206   ```ts
207   V128.7
208   ```
209
210   Draw a vertical line from point (162, 467.1) to point (162, 128.7).
211
212   ```ts
213   z
214   ```
215
216   Close the current subpath.
217
218   ![drawing-feature4](figures/drawing-feature4.png)
219
220   In the sample code, the fill color is white and the stroke is transparent.
221
222   ```ts
223   .fill(Color.White)
224   .stroke(Color.Transparent)
225   ```
226
227   ```ts
228   @Entry
229   @Component
230   struct Logo {
231     build() {
232       Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
233         Shape() {
234           Path()
235             .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
236             .fill(Color.White)
237             .stroke(Color.Transparent)
238         }
239         .height('630px')
240         .width('630px')
241       }
242       .width('100%')
243       .height('100%')
244       .linearGradient(
245         {
246           angle: 180,
247           colors: [['#BDE895', 0.1], ["#95DE7F", 0.6],  ["#7AB967", 1]]
248         })
249     }
250   }
251   ```
252
253   ![drawing-feature5](figures/drawing-feature5.png)
254
2556. Draw the second path. Fill the shape background with gradient colors. Because the gradient colors fill the entire box, you must use the **clip** method with the **Shape** as the input parameter so that the path is clipped.
256
257   ```ts
258   Path()
259     .commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z')
260     .fill('none')
261     .stroke(Corlor.Transparent)
262     .linearGradient(
263     {
264       angle: 30,
265       colors: [["#C4FFA0", 0],  ["#ffffff", 1]]
266     })
267     .clip(new Path().commands('M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'))
268   ```
269
270   The path drawing command is long. You can call the command by using it as a member variable of the component through **this**.
271
272   ```ts
273   @Entry
274   @Component
275   struct Logo {
276     private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
277     build() {
278       ......
279           Path()
280             .commands(this.pathCommands1)
281             .fill('none')
282             .stroke(Color.Transparent)
283             .linearGradient(
284             {
285               angle: 30,
286               colors: [["#C4FFA0", 0],  ["#ffffff", 1]]
287             })
288             .clip(new Path().commands(this.pathCommands1))
289        ......
290     }
291   }
292   ```
293
294   ![drawing-feature6](figures/drawing-feature6.png)
295
2967. Draw the third path.
297
298   ```ts
299   @Entry
300   @Component
301   struct Logo {
302     private pathCommands1:string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
303     private pathCommands2:string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'
304     build() {
305       Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
306         Shape() {
307           Path()
308             .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
309             .fill(Color.White)
310             .stroke(Color.Transparent)
311
312           Path()
313             .commands(this.pathCommands1)
314             .fill('none')
315             .stroke(Color.Transparent)
316             .linearGradient(
317             {
318               angle: 30,
319               colors: [["#C4FFA0", 0],  ["#ffffff", 1]]
320             })
321             .clip(new Path().commands(this.pathCommands1))
322
323           Path()
324             .commands(this.pathCommands2)
325             .fill('none')
326             .stroke(Color.Transparent)
327             .linearGradient(
328             {
329               angle: 50,
330               colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4],  ["#ffffff", 0.7]]
331             })
332             .clip(new Path().commands(this.pathCommands2))
333         }
334         .height('630px')
335         .width('630px')
336       }
337       .width('100%')
338       .height('100%')
339       .linearGradient(
340         {
341           angle: 180,
342           colors: [['#BDE895', 0.1], ["#95DE7F", 0.6],  ["#7AB967", 1]]
343         })
344     }
345   }
346   ```
347
348   ![drawing-feature7](figures/drawing-feature7.png)
349
350   The drawing of the application logo is now completed. This logo combines three **\<Path>** components through SVG commands and takes the shape of an artistic leaf.
351
3528. Add the application title and slogan.
353
354   ```ts
355   @Entry
356   @Component
357   struct Logo {
358     private pathCommands1: string = 'M319.5 128.1 c103.5 0 187.5 84 187.5 187.5 v15 a172.5 172.5 0 0 3 -172.5 172.5 H198 a36 36 0 0 3 -13.8 -1 207 207 0 0 0 87 -372 h48.3 z'
359     private pathCommands2: string = 'M270.6 128.1 h48.6 c51.6 0 98.4 21 132.3 54.6 a411 411 0 0 3 -45.6 123 c-25.2 45.6 -56.4 84 -87.6 110.4 a206.1 206.1 0 0 0 -47.7 -288 z'
360
361     build() {
362       Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
363         Shape() {
364           Path()
365             .commands('M162 128.7 a222 222 0 0 1 100.8 374.4 H198 a36 36 0 0 3 -36 -36')
366             .fill(Color.White)
367             .stroke(Color.Transparent)
368
369           Path()
370             .commands(this.pathCommands1)
371             .fill('none')
372             .stroke(Color.Transparent)
373             .linearGradient(
374               {
375                 angle: 30,
376                 colors: [["#C4FFA0", 0], ["#ffffff", 1]]
377               })
378             .clip(new Path().commands(this.pathCommands1))
379
380           Path()
381             .commands(this.pathCommands2)
382             .fill('none')
383             .stroke(Color.Transparent)
384             .linearGradient(
385               {
386                 angle: 50,
387                 colors: [['#8CC36A', 0.1], ["#B3EB90", 0.4], ["#ffffff", 0.7]]
388               })
389             .clip(new Path().commands(this.pathCommands2))
390         }
391         .height('630px')
392         .width('630px')
393
394         Text('Healthy Diet')
395           .fontSize(26)
396           .fontColor(Color.White)
397           .margin({ top: 300 })
398
399         Text('Healthy life comes from a balanced diet')
400           .fontSize(17)
401           .fontColor(Color.White)
402           .margin({ top: 4 })
403       }
404       .width('100%')
405       .height('100%')
406       .linearGradient(
407         {
408           angle: 180,
409           colors: [['#BDE895', 0.1], ["#95DE7F", 0.6], ["#7AB967", 1]]
410        })
411     }
412   }
413   ```
414
415   ![drawing-feature8](figures/drawing-feature8.png)
416