• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Drawing Modifier
2
3If the drawn content of some components does not meet the requirements, you can use the custom drawing features to draw part or all of the components to achieve the expected effect. For example, you can create buttons in special shapes or icons that mix text and imagery. The drawing modifier offers higher flexibility in your custom drawing.
4
5>  **NOTE**
6>
7>  This feature is supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version.
8
9## drawModifier
10
11drawModifier(modifier: DrawModifier | undefined)
12
13Creates a drawing modifier.
14
15**Atomic service API**: This API can be used in atomic services since API version 12.
16
17**System capability**: SystemCapability.ArkUI.ArkUI.Full
18
19**Supported components:**
20
21AlphabetIndexer, Badge, Blank, Button, CalendarPicker, Checkbox, CheckboxGroup, Circle, Column, ColumnSplit, Counter, DataPanel, DatePicker, Ellipse, Flex, FlowItem, FolderStack, FormLink, Gauge, Grid, GridCol, GridItem, GridRow, Hyperlink, Image, ImageAnimator, ImageSpan, Line, List, ListItem, ListItemGroup, LoadingProgress, Marquee, Menu, MenuItem, MenuItemGroup, NavDestination, Navigation, Navigator, NavRouter, NodeContainer, Path, PatternLock, Polygon, Polyline, Progress, QRCode, Radio, Rating, Rect, Refresh, RelativeContainer, RichEditor, Row, RowSplit, Scroll, ScrollBar, Search, Select, Shape, SideBarContainer, Slider, Stack, Stepper, StepperItem, Swiper, SymbolGlyph, TabContent, Tabs, Text, TextArea, TextClock, TextInput, TextPicker, TextTimer, TimePicker, Toggle, WaterFlow, XComponent
22
23**Parameters**
24
25| Name| Type                                                | Mandatory| Description                                                        |
26| ------ | ---------------------------------------------------- | ---- | ------------------------------------------------------------ |
27| modifier  |  [DrawModifier](#drawmodifier-1) \| undefined | Yes  | Custom drawing modifier, which defines the logic of custom drawing.<br> Default value: **undefined**<br>**NOTE**<br> A custom modifier applies only to the FrameNode of the currently bound component, not to its subnodes.|
28
29## DrawModifier
30
31Implements a **DrawModifier** instance for using the **drawFront**, **drawContent**, and **drawBehind** methods for custom drawing as well as the **invalidate** method for redrawing. Each **DrawModifier** instance can be set for only one component. Repeated setting is not allowed.
32
33**Atomic service API**: This API can be used in atomic services since API version 12.
34
35**System capability**: SystemCapability.ArkUI.ArkUI.Full
36
37### drawFront
38
39drawFront?(drawContext: DrawContext): void
40
41Draws the foreground. This method can be overloaded for custom foreground drawing.
42
43**Atomic service API**: This API can be used in atomic services since API version 12.
44
45**System capability**: SystemCapability.ArkUI.ArkUI.Full
46
47**Parameters**
48
49| Name | Type                                                  | Mandatory| Description            |
50| ------- | ------------------------------------------------------ | ---- | ---------------- |
51| drawContext | [DrawContext](../js-apis-arkui-graphics.md#drawcontext) | Yes  | Graphics drawing context.|
52
53### drawContent
54
55drawContent?(drawContext: DrawContext): void
56
57Draws the content. This method can be overloaded for custom content drawing. The overloaded method will replace the original content drawing function of the component.
58
59**Atomic service API**: This API can be used in atomic services since API version 12.
60
61**System capability**: SystemCapability.ArkUI.ArkUI.Full
62
63**Parameters**
64
65| Name | Type                                                  | Mandatory| Description            |
66| ------- | ------------------------------------------------------ | ---- | ---------------- |
67| drawContext | [DrawContext](../js-apis-arkui-graphics.md#drawcontext) | Yes  | Graphics drawing context.|
68
69### drawBehind
70
71drawBehind?(drawContext: DrawContext): void
72
73Draws the background. This method can be overloaded for custom background drawing.
74
75**Atomic service API**: This API can be used in atomic services since API version 12.
76
77**System capability**: SystemCapability.ArkUI.ArkUI.Full
78
79**Parameters**
80
81| Name | Type                                                  | Mandatory| Description            |
82| ------- | ------------------------------------------------------ | ---- | ---------------- |
83| drawContext | [DrawContext](../js-apis-arkui-graphics.md#drawcontext) | Yes  | Graphics drawing context.|
84
85
86### invalidate
87
88invalidate(): void
89
90Triggers redrawing of the bound component. No overloading is allowed or needed.
91
92**Atomic service API**: This API can be used in atomic services since API version 12.
93
94**System capability**: SystemCapability.ArkUI.ArkUI.Full
95
96## Example
97
98This example shows how to customize the drawing of a **Text** component using **DrawModifier**.
99
100```ts
101// xxx.ets
102import { drawing } from '@kit.ArkGraphics2D';
103import { AnimatorResult } from '@kit.ArkUI';
104
105class MyFullDrawModifier extends DrawModifier {
106  public scaleX: number = 1;
107  public scaleY: number = 1;
108
109  drawBehind(context: DrawContext): void {
110    const brush = new drawing.Brush();
111    brush.setColor({
112      alpha: 255,
113      red: 255,
114      green: 0,
115      blue: 0
116    });
117    context.canvas.attachBrush(brush);
118    const halfWidth = context.size.width / 2;
119    const halfHeight = context.size.width / 2;
120    context.canvas.drawRect({
121      left: vp2px(halfWidth - 50 * this.scaleX),
122      top: vp2px(halfHeight - 50 * this.scaleY),
123      right: vp2px(halfWidth + 50 * this.scaleX),
124      bottom: vp2px(halfHeight + 50 * this.scaleY)
125    });
126  }
127
128  drawContent(context: DrawContext): void {
129    const brush = new drawing.Brush();
130    brush.setColor({
131      alpha: 255,
132      red: 0,
133      green: 255,
134      blue: 0
135    });
136    context.canvas.attachBrush(brush);
137    const halfWidth = context.size.width / 2;
138    const halfHeight = context.size.width / 2;
139    context.canvas.drawRect({
140      left: vp2px(halfWidth - 30 * this.scaleX),
141      top: vp2px(halfHeight - 30 * this.scaleY),
142      right: vp2px(halfWidth + 30 * this.scaleX),
143      bottom: vp2px(halfHeight + 30 * this.scaleY)
144    });
145  }
146
147  drawFront(context: DrawContext): void {
148    const brush = new drawing.Brush();
149    brush.setColor({
150      alpha: 255,
151      red: 0,
152      green: 0,
153      blue: 255
154    });
155    context.canvas.attachBrush(brush);
156    const halfWidth = context.size.width / 2;
157    const halfHeight = context.size.width / 2;
158    const radiusScale = (this.scaleX + this.scaleY) / 2;
159    context.canvas.drawCircle(vp2px(halfWidth), vp2px(halfHeight), vp2px(20 * radiusScale));
160  }
161}
162
163class MyFrontDrawModifier extends DrawModifier {
164  public scaleX: number = 1;
165  public scaleY: number = 1;
166
167  drawFront(context: DrawContext): void {
168    const brush = new drawing.Brush();
169    brush.setColor({
170      alpha: 255,
171      red: 0,
172      green: 0,
173      blue: 255
174    });
175    context.canvas.attachBrush(brush);
176    const halfWidth = context.size.width / 2;
177    const halfHeight = context.size.width / 2;
178    const radiusScale = (this.scaleX + this.scaleY) / 2;
179    context.canvas.drawCircle(vp2px(halfWidth), vp2px(halfHeight), vp2px(20 * radiusScale));
180  }
181}
182
183@Entry
184@Component
185struct DrawModifierExample {
186  private fullModifier: MyFullDrawModifier = new MyFullDrawModifier();
187  private frontModifier: MyFrontDrawModifier = new MyFrontDrawModifier();
188  private drawAnimator: AnimatorResult | undefined = undefined;
189  @State modifier: DrawModifier = new MyFrontDrawModifier();
190  private count = 0;
191
192  create() {
193    let self = this;
194    this.drawAnimator = this.getUIContext().createAnimator({
195      duration: 1000,
196      easing: 'ease',
197      delay: 0,
198      fill: 'forwards',
199      direction: 'normal',
200      iterations: 1,
201      begin: 0,
202      end: 2
203    });
204    this.drawAnimator.onFrame = (value: number) => {
205      console.log('frame value =', value);
206      const tempModifier = self.modifier as MyFullDrawModifier | MyFrontDrawModifier;
207      tempModifier.scaleX = Math.abs(value - 1);
208      tempModifier.scaleY = Math.abs(value - 1);
209      self.modifier.invalidate();
210    };
211  }
212
213  build() {
214    Column() {
215      Row() {
216        Text('test text')
217          .width(100)
218          .height(100)
219          .margin(10)
220          .backgroundColor(Color.Gray)
221          .onClick(() => {
222            const tempModifier = this.modifier as MyFullDrawModifier | MyFrontDrawModifier;
223            tempModifier.scaleX -= 0.1;
224            tempModifier.scaleY -= 0.1;
225          })
226          .drawModifier(this.modifier)
227      }
228
229      Row() {
230        Button('create')
231          .width(100)
232          .height(100)
233          .margin(10)
234          .onClick(() => {
235            this.create();
236          })
237        Button('play')
238          .width(100)
239          .height(100)
240          .margin(10)
241          .onClick(() => {
242            if (this.drawAnimator) {
243              this.drawAnimator.play();
244            }
245          })
246        Button('changeModifier')
247          .width(100)
248          .height(100)
249          .margin(10)
250          .onClick(() => {
251            this.count += 1;
252            if (this.count % 2 === 1) {
253              console.log('change to full modifier');
254              this.modifier = this.fullModifier;
255            } else {
256              console.log('change to front modifier');
257              this.modifier = this.frontModifier;
258            }
259          })
260      }
261    }
262    .width('100%')
263    .height('100%')
264  }
265}
266```
267
268![drawModifier.gif](figures/drawModifier.gif)
269