• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Transition Animation Within a Component
2
3
4The process of inserting and deleting a component is the transition process of the component. The animation of inserting and deleting a component is called the transition animation in the component. You can define the appearance and disappearance effects of a component through the transition animation in the component.
5
6
7The API of the transition animation in the component is as follows:
8
9
10
11```ts
12transition(value: TransitionOptions)
13```
14
15
16The input parameter of the [transition](../reference/arkui-ts/ts-transition-animation-component.md) function is the transition effect in the component. You can define the transition effect of one or more transition styles such as translation, transparency, rotation, and scaling. This parameter must be used together with [animateTo] (arkts-layout-update-animation.md# uses explicit animation to generate layout update animation). The component transition effect can be generated only when they are used together.
17
18
19## Common Usage of Transition
20
21The type parameter is used to specify the gadget change scenario where the current transition dynamic effect takes effect. The type is [TransitionType](../reference/arkui-ts/ts-appendix-enums.md#transitiontype).
22
23- The same animation effect is used for inserting and deleting components.
24
25  ```ts
26  Button()
27    .transition({ type: TransitionType.All, scale: { x: 0, y: 0 } })
28  ```
29
30  When the type attribute is TransitionType.All, the specified transition effect takes effect in all change (insertion and deletion) scenarios of the component. In this case, deleting the animation and inserting the animation are reverse processes, and deleting the animation is reverse playing of inserting the animation. For example, the preceding code defines a Button control. When a component is inserted, the component changes from the state where x and y of the scale are both 0 to the default state where x and y of the scale are both 1 (complete display). The component is gradually zoomed in. When a component is deleted, the component changes from the default state where x and y of the scale are 1 to the state where x and y of the specified scale are 0 and gradually shrinks to 0.
31
32
33- Different animation effects are used for inserting and deleting components.
34
35  ```ts
36  Button()
37    .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 }, opacity: 0 })
38    .transition({ type: TransitionType.Delete, rotate: { x: 0, y: 0, z: 1, angle: 360 } })
39  ```
40
41  When different transition animation effects need to be implemented for component insertion and deletion, you can call the transition function twice to set the type attribute to TransitionType.Insert and TransitionType.Delete respectively. For example, the preceding code defines a Button control. When the component is inserted, the component changes from an initial state in which the position is translated by 200 vp in the x direction and the position is translated by –200 vp in the y direction relative to the normal layout position of the component, and the transparency is 0 in the x and y directions to a default state in which the translation amount is 0 and the transparency is 1. The inserted animation is a combination of a translation animation and a transparency animation. When the component is deleted, the component changes from the default state in which the rotation angle is 0 to the end state in which the component rotates 360 degrees around the z axis, that is, rotates around the z axis for one week.
42
43
44- Define only one of the animation effects of inserting or deleting a component.
45
46  ```ts
47  Button()
48    .transition({ type: TransitionType.Delete, translate: { x: 200, y: -200 } })
49  ```
50
51  If only the transition animation effect of component insertion or deletion is required, you only need to set the transition effect whose type attribute is TransitionType.Insert or TransitionType.Delete. For example, the preceding code defines a Button control. When a component is deleted, the component is moved from the normal position without translation to the position of 200 vp in the x direction and -200 vp in the y direction relative to the normal layout position. Inserting the component does not generate a transition animation for the component.
52
53
54## if/else: generates transition animations in components.
55
56The if/else statement can control the insertion and deletion of components. The following code can be used to control whether the if condition is met through the button click event to control whether to display the Image component under if.
57
58
59
60```ts
61@Entry
62@Component
63struct IfElseTransition {
64  @State flag: boolean = true;
65  @State show: string = 'show';
66
67  build() {
68    Column() {
69      Button(this.show).width(80).height(30).margin(30)
70        .onClick(() => {
71          if (this.flag) {
72            this.show = 'hide';
73          } else {
74            this.show = 'show';
75          }
76          //Click the button to control the display and disappearance of the image.
77          this.flag = !this.flag;
78        })
79      if (this.flag) {
80          Image($r('app.media.mountain')).width(200).height(200)
81      }
82    }.height('100%').width('100%')
83  }
84}
85```
86
87
88No animation is configured in the preceding code. Next, we'll add the in-component transition effect to the above code. The Image component is controlled by if. You need to add the transition parameter to the Image component to specify the transition effect in the component. For example, you can add the translation effect when inserting the file, and add the scaling and transparency effects when deleting the file.
89
90
91
92```ts
93if (this.flag) {
94  Image($r('app.media.mountain')).width(200).height(200)
95    .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 } })
96    .transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })
97}
98```
99
100
101Although the preceding code specifies the animation style, the animation parameters are not specified. Therefore, you do not know how long and how to use the curve to complete the animation. Transition must be used together with animateTo. In the closure of animateTo, transition controls the insertion and deletion of components. The preceding sample code is used to change the value of flag in the animateTo closure. The code is as follows: Set the animation duration to 1000 ms, use the default curve of the animateTo function, and change the value of flag. Animation is generated based on the animation parameter for all changes caused by flag changes. Here, the flag affects the appearance and disappearance of the image.
102
103
104
105```ts
106animateTo({ duration: 1000 }, () => {
107  this.flag = !this.flag;
108})
109```
110
111
112After the preceding process, when animateTo and transition are used together, the transition animation in the component is generated. The complete sample code is as follows:
113
114
115
116```ts
117@Entry
118@Component
119struct IfElseTransition {
120  @State flag: boolean = true;
121  @State show: string = 'show';
122
123  build() {
124    Column() {
125      Button(this.show).width(80).height(30).margin(30)
126        .onClick(() => {
127          if (this.flag) {
128            this.show = 'hide';
129          } else {
130            this.show = 'show';
131          }
132
133          animateTo({ duration: 1000 }, () => {
134            //Control the appearance and disappearance of the Image component in the animation closure.
135            this.flag = !this.flag;
136          })
137        })
138      if (this.flag) {
139        //The appearance and disappearance of the image are configured as different transition effects.
140        Image($r('app.media.mountain')).width(200).height(200)
141          .transition({ type: TransitionType.Insert, translate: { x: 200, y: -200 } })
142          .transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })
143      }
144    }.height('100%').width('100%')
145  }
146}
147```
148
149
150![ifElseTransition](figures/ifElseTransition.gif)
151
152
153>**NOTE**
154>
155>When the transition effect is set to translate or scale, the animation process may exceed the range of the parent component after the translation or magnification is overlaid on the position. If you want the child component to be completely displayed when the parent component is beyond the range of the parent component, you can set the clip attribute of the parent component to false so that the parent component does not tailor the child component. If you want the excess child components not to be displayed when the parent component is exceeded, you can set the clip attribute of the parent component to true to tailor the excess child components.
156
157
158## Forach generates transition animations in components.
159
160Similar to if/else, Forach can control the insertion and deletion of components by controlling the number of elements in an array. To use Forach to generate an intra-component transition animation, the following conditions must be met:
161
162- The transition effect is configured for the component in Forach.
163
164- Controls the insertion or deletion of components in the closure of animateTo, that is, controls the addition and deletion of array elements.
165
166
167The following code is an example of using Forach to generate an in-component transition animation.
168
169
170
171```ts
172@Entry
173@Component
174struct ForEachTransition {
175  @State numbers: string[] = ["1", "2", "3", "4", "5"]
176  startNumber: number = 6;
177
178  build() {
179    Column({ space: 10 }) {
180      Column() {
181        ForEach(this.numbers, (item) => {
182          // The transition effect needs to be configured for the direct component under Forach.
183          Text(item)
184            .width(240)
185            .height(60)
186            .fontSize(18)
187            .borderWidth(1)
188            .backgroundColor(Color.Orange)
189            .textAlign(TextAlign.Center)
190            .transition({ type: TransitionType.All, translate: { x: 200 }, scale: { x: 0, y: 0 } })
191        }, item => item)
192      }
193      .margin(10)
194      .justifyContent(FlexAlign.Start)
195      .alignItems(HorizontalAlign.Center)
196      .width("90%")
197      .height("70%")
198
199      Button ('Add element to header')
200        .fontSize(16)
201        .width(160)
202        .onClick(() => {
203          animateTo({ duration: 1000 }, () => {
204            //Insert an element to the array header. As a result, Forach adds the corresponding component to the header.
205            this.numbers.unshift(this.startNumber.toString());
206            this.startNumber++;
207          })
208        })
209      Button ('Add element to tail')
210        .width(160)
211        .fontSize(16)
212        .onClick(() => {
213          animateTo({ duration: 1000 }, () => {
214            //Insert an element to the end of the array. As a result, Forach adds the corresponding component to the end.
215            this.numbers.push(this.startNumber.toString());
216            this.startNumber++;
217          })
218        })
219      Button ('Delete Header Element')
220        .width(160)
221        .fontSize(16)
222        .onClick(() => {
223          animateTo({ duration: 1000 }, () => {
224            //Delete the header element of the array. As a result, Forach deletes the header component.
225            this.numbers.shift();
226          })
227        })
228      Button ('Delete Tail Element')
229        .width(160)
230        .fontSize(16)
231        .onClick(() => {
232          animateTo({ duration: 1000 }, () => {
233            //Delete the tail element of the array. As a result, Forach deletes the header component.
234            this.numbers.pop();
235          })
236        })
237    }
238    .width('100%')
239    .height('100%')
240  }
241}
242```
243
244
245The display effect is shown below.
246
247
248![forEachTransition2](figures/forEachTransition2.gif)
249
250
251The column layout mode is set to FlexAlign.Start, that is, the vertical layout starts from the head. Therefore, when an element is added to the end of an array, the position of the component corresponding to the existing element in the array is not affected, and only the insertion animation of the new component is triggered. When an element is added to the array header, the subscripts of all elements in the original array are added. Although the addition or deletion of the element is not triggered, the location of the corresponding component is affected. Therefore, in addition to the transition animation for new components, the position animation is also performed for components in Forach.
252
253
254>**NOTE**
255>
256>If/else and ForEach are syntax nodes. The component for configuring the transition effect in the component should be directly used as the child of the syntax node. If a component is added or deleted due to the addition or deletion of a syntax node, only the intra-component transition animation of the direct child component can be triggered. Developers should not expect the component transition animation to be generated for deeper components.
257