• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 出现/消失转场
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @CCFFWW-->
5<!--Designer: @yangfan229-->
6<!--Tester: @lxl007-->
7<!--Adviser: @HelloCrease-->
8
9
10[transition](../reference/apis-arkui/arkui-ts/ts-transition-animation-component.md)是基础的组件转场接口,用于实现一个组件出现或者消失时的动画效果。可以通过[TransitionEffect对象](../reference/apis-arkui/arkui-ts/ts-transition-animation-component.md#transitioneffect10对象说明)的组合使用,定义出各式效果。
11
12
13  **表1** 转场效果接口
14
15| 转场效果 | 说明 | 动画 |
16| -------- | -------- | -------- |
17| IDENTITY | 禁用转场效果。 | 无。 |
18| OPACITY | 默认的转场效果,透明度转场。 | 出现时透明度从0到1,消失时透明度从1到0。 |
19| SLIDE | 滑动转场效果。 | 出现时从窗口左侧滑入,消失时从窗口右侧滑出。 |
20| translate | 通过设置组件平移创建转场效果。 | 出现时为translate接口设置的值到默认值0,消失时为默认值0到translate接口设置的值。 |
21| rotate | 通过设置组件旋转创建转场效果。 | 出现时为rotate接口设置的值到默认值0,消失时为默认值0到rotate接口设置的值。 |
22| opacity | 通过设置透明度参数创建转场效果。 | 出现时为opacity设置的值到默认透明度1,消失时为默认透明度1到opacity设置的值。 |
23| move | 通过[TransitionEdge](../reference/apis-arkui/arkui-ts/ts-transition-animation-component.md#transitionedge10)创建从窗口哪条边缘出来的效果。 | 出现时从TransitionEdge方向滑入,消失时滑出到TransitionEdge方向。 |
24| asymmetric | 通过此方法组合非对称的出现消失转场效果。<br/>- appear:出现转场的效果。<br/>- disappear:消失转场的效果。 | 出现时采用appear设置的TransitionEffect出现效果,消失时采用disappear设置的TransitionEffect消失效果。 |
25| combine | 组合其他TransitionEffect。 | 组合其他TransitionEffect,一起生效。 |
26| animation | 定义转场效果的动画参数:<br/>-&nbsp;如果不定义会跟随animateTo的动画参数。<br/>-&nbsp;不支持通过控件的animation接口配置动画参数。<br/>-&nbsp;TransitionEffect中animation的onFinish不生效。 | 调用顺序时从上往下,上面TransitionEffect的animation也会作用到下面TransitionEffect。 |
27
28
291. 创建TransitionEffect。
30
31   ```ts
32   // 出现时会是所有转场效果的出现效果叠加,消失时会是所有消失转场效果的叠加
33   // 说明各个effect跟随的动画参数
34   private effect: object =
35     TransitionEffect.OPACITY // 创建了透明度转场效果,这里没有调用animation接口,会跟随animateTo的动画参数
36       // 通过combine方法,添加缩放转场效果,并指定了springMotion(0.6, 1.2)曲线
37       .combine(TransitionEffect.scale({ x: 0, y: 0 }).animation({ curve: curves.springMotion(0.6, 1.2) }))
38       // 添加旋转转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 1.2)
39       .combine(TransitionEffect.rotate({ angle: 90 }))
40       // 添加平移转场效果,动画参数会跟随其之上带animation的TransitionEffect,也就是springMotion(0.6, 1.2)
41       .combine(TransitionEffect.translate({ x: 150, y: 150 }))
42       // 添加move转场效果,并指定了springMotion曲线
43       .combine(TransitionEffect.move(TransitionEdge.END)).animation({curve: curves.springMotion()})
44       // 添加非对称的转场效果,由于这里没有设置animation,会跟随上面的TransitionEffect的animation效果,也就是springMotion
45       .combine(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 0, y: 0 }), TransitionEffect.rotate({ angle: 90 })));
46   ```
47
482. 将转场效果通过[transition](../reference/apis-arkui/arkui-ts/ts-transition-animation-component.md)接口设置到组件。
49
50   ```ts
51   Text('test')
52     .transition(this.effect)
53   ```
54
553. 新增或者删除组件触发转场。
56
57   ```ts
58   @State isPresent: boolean = true;
59   // ...
60   if (this.isPresent) {
61     Text('test')
62       .transition(this.effect)
63   }
64   // ...
65   // 控制新增或者删除组件
66   // 方式一:将控制变量放到animateTo闭包内,未通过animation接口定义动画参数的TransitionEffect将跟随animateTo的动画参数
67   this.getUIContext()?.animateTo({ curve: curves.springMotion() }, () => {
68     this.isPresent = false;
69   })
70
71   // 方式二:直接控制删除或者新增组件,动画参数由TransitionEffect的animation接口配置
72   this.isPresent = false;
73   ```
74
75
76 完整的示例代码和效果如下,示例中采用直接删除或新增组件的方式触发转场,也可以替换为在animateTo闭包内改变控制变量触发转场。
77
78```ts
79import { curves } from '@kit.ArkUI';
80
81@Entry
82@Component
83struct TransitionEffectDemo {
84  @State isPresent: boolean = false;
85  // 第一步,创建TransitionEffect
86  private effect: TransitionEffect =
87    // 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线
88    TransitionEffect.OPACITY.animation({
89      curve: curves.springMotion(0.6, 0.8)
90    })// 通过combine方法,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 0.8)
91      .combine(TransitionEffect.scale({
92        x: 0,
93        y: 0
94      }))// 添加旋转转场效果,这里的动画参数会跟随上面带animation的TransitionEffect,也就是springMotion(0.6, 0.8)
95      .combine(TransitionEffect.rotate({ angle: 90 }))// 添加平移转场效果,这里的动画参数使用指定的springMotion()
96      .combine(TransitionEffect.translate({ y: 150 })
97        .animation({ curve: curves.springMotion() }))// 添加move转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion()
98      .combine(TransitionEffect.move(TransitionEdge.END));
99
100  build() {
101    Stack() {
102      if (this.isPresent) {
103        Column() {
104          Text('ArkUI')
105            .fontWeight(FontWeight.Bold)
106            .fontSize(20)
107            .fontColor(Color.White)
108        }
109        .justifyContent(FlexAlign.Center)
110        .width(150)
111        .height(150)
112        .borderRadius(10)
113        .backgroundColor(0xf56c6c)
114        // 第二步:将转场效果通过transition接口设置到组件
115        .transition(this.effect)
116      }
117
118      // 边框
119      Column()
120        .width(155)
121        .height(155)
122        .border({
123          width: 5,
124          radius: 10,
125          color: Color.Black
126        })
127
128      // 第三步:新增或者删除组件触发转场,控制新增或者删除组件
129      Button('Click')
130        .margin({ top: 320 })
131        .onClick(() => {
132          this.isPresent = !this.isPresent;
133        })
134    }
135    .width('100%')
136    .height('60%')
137  }
138}
139```
140
141
142
143![zh-cn_image_0000001599818064](figures/zh-cn_image_0000001599818064.gif)
144
145
146对多个组件添加转场效果时,可以在animation动画参数中配置不同的delay值,实现组件渐次出现消失的效果:
147
148```ts
149const ITEM_COUNTS = 9;
150const ITEM_COLOR = '#ED6F21';
151const INTERVAL = 30;
152const DURATION = 300;
153
154@Entry
155@Component
156struct Index1 {
157  @State isGridShow: boolean = false;
158  private dataArray: number[] = new Array(ITEM_COUNTS);
159
160  aboutToAppear(): void {
161    for (let i = 0; i < ITEM_COUNTS; i++) {
162      this.dataArray[i] = i;
163    }
164  }
165
166  build() {
167    Stack() {
168      if (this.isGridShow) {
169        Grid() {
170          ForEach(this.dataArray, (item: number, index: number) => {
171            GridItem() {
172              Stack() {
173                Text((item + 1).toString())
174              }
175              .size({ width: 50, height: 50 })
176              .backgroundColor(ITEM_COLOR)
177              .transition(TransitionEffect.OPACITY
178                .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 }))// 对每个方格的转场添加delay,实现组件的渐次出现消失效果
179                .animation({ duration: DURATION, curve: Curve.Friction, delay: INTERVAL * index }))
180              .borderRadius(10)
181            }
182            // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
183            // 此处让方格的父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
184            .transition(TransitionEffect.opacity(0.99))
185          }, (item: number) => item.toString())
186        }
187        .columnsTemplate('1fr 1fr 1fr')
188        .rowsGap(15)
189        .columnsGap(15)
190        .size({ width: 180, height: 180 })
191        // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
192        // 此处让父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
193        .transition(TransitionEffect.opacity(0.99))
194      }
195    }
196    .size({ width: '100%', height: '100%' })
197    .onClick(() => {
198      this.getUIContext()?.animateTo({
199        duration: DURATION + INTERVAL * (ITEM_COUNTS - 1),
200        curve: Curve.Friction
201      }, () => {
202        this.isGridShow = !this.isGridShow;
203      })
204    })
205  }
206}
207```
208
209![zh-cn_image_0000001599818064](figures/zh-cn_image_0000001599818065.gif)