1# 页面转场动画 (不推荐)
2
3为了实现更好的转场效果,推荐使用[导航转场](arkts-navigation-transition.md)和[模态转场](arkts-modal-transition.md)。
4
5两个页面间发生跳转,一个页面消失,另一个页面出现,这时可以配置各自页面的页面转场参数实现自定义的页面转场效果。[页面转场](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md)效果写在pageTransition函数中,通过[PageTransitionEnter](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#pagetransitionenter)和[PageTransitionExit](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#pagetransitionexit)指定页面进入和退出的动画效果。
6pageTransition的函数为:
7
8```ts
9pageTransition() {
10  PageTransitionEnter()
11  PageTransitionExit()
12}
13```
14
15
16PageTransitionEnter的接口为:
17
18```ts
19PageTransitionEnter({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number})
20```
21
22
23PageTransitionExit的接口为:
24
25```ts
26PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number})
27```
28
29
30上述接口定义了PageTransitionEnter和PageTransitionExit组件,可通过slide、translate、scale、opacity属性定义不同的页面转场效果。对于PageTransitionEnter而言,这些效果表示入场时起点值,对于PageTransitionExit而言,这些效果表示退场的终点值,这一点与组件转场transition配置方法类似。此外,PageTransitionEnter提供了onEnter接口进行自定义页面入场动画的回调,PageTransitionExit提供了onExit接口进行自定义页面退场动画的回调。
31
32
33上述接口中的参数type,表示路由生效的类型,这一点开发者容易混淆其含义。页面转场的两个页面,必定有一个页面退出,一个页面进入。如果通过router.pushUrl操作从页面A跳转到页面B,则页面A退出,做页面退场动画,页面B进入,做页面入场动画。如果通过router.back操作从页面B返回到页面A,则页面B退出,做页面退场动画,页面A进入,做页面入场动画。即页面的PageTransitionEnter既可能是由于新增页面(push,入栈)引起的新页面的入场动画,也可能是由于页面返回(back,或pop,出栈)引起的页面栈中老页面的入场动画,为了能区分这两种形式的入场动画,提供了type参数,这样开发者能完全定义所有类型的页面转场效果。
34
35
36## type配置为RouteType.None
37
38type为RouteType.None表示对页面栈的push、pop操作均生效,type的默认值为RouteType.None39
40
41```ts
42// page A
43pageTransition() {
44  // 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效
45  PageTransitionEnter({ type: RouteType.None, duration: 1200 })
46    .slide(SlideEffect.Left)
47  // 定义页面退出时的效果,向左侧滑出,时长为1000ms,无论页面栈发生push还是pop操作均可生效
48  PageTransitionExit({ type: RouteType.None, duration: 1000 })
49    .slide(SlideEffect.Left)
50}
51```
52
53```ts
54// page B
55pageTransition() {
56  // 定义页面进入时的效果,从右侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效
57  PageTransitionEnter({ type: RouteType.None, duration: 1000 })
58    .slide(SlideEffect.Right)
59  // 定义页面退出时的效果,向右侧滑出,时长为1200ms,无论页面栈发生push还是pop操作均可生效
60  PageTransitionExit({ type: RouteType.None, duration: 1200 })
61    .slide(SlideEffect.Right)
62}
63```
64
65
66假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。
67
68
69| 路由操作                         | 页面A转场效果                            | 页面B转场效果                            |
70| ---------------------------- | ---------------------------------- | ---------------------------------- |
71| router.pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit生效,向左侧滑出屏幕  | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 |
72| router.back,从页面B返回到页面A       | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕  |
73| router.pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕  |
74| router.back,从页面A返回到页面B       | 页面退出,PageTransitionExit生效,向左侧滑出屏幕  | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 |
75
76
77如果希望pushUrl进入的页面总是从右侧滑入,back时退出的页面总是从右侧滑出,则上表中的第3、4种情况不满足要求,那么需要完整的定义4个页面转场效果。
78
79
80## type配置为RouteType.PushRouteType.Pop
81
82type为RouteType.Push表示仅对页面栈的push操作生效,type为RouteType.Pop表示仅对页面栈的pop操作生效。
83
84
85```ts
86// page A
87pageTransition() {
88  // 定义页面进入时的效果,从右侧滑入,时长为1200ms,页面栈发生push操作时该效果才生效
89  PageTransitionEnter({ type: RouteType.Push, duration: 1200 })
90    .slide(SlideEffect.Right)
91  // 定义页面进入时的效果,从左侧滑入,时长为1200ms,页面栈发生pop操作时该效果才生效
92  PageTransitionEnter({ type: RouteType.Pop, duration: 1200 })
93    .slide(SlideEffect.Left)
94  // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
95  PageTransitionExit({ type: RouteType.Push, duration: 1000 })
96    .slide(SlideEffect.Left)
97  // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
98  PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
99    .slide(SlideEffect.Right)
100}
101```
102
103```ts
104// page B
105pageTransition() {
106  // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
107  PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
108    .slide(SlideEffect.Right)
109  // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
110  PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
111    .slide(SlideEffect.Left)
112  // 定义页面退出时的效果,向左侧滑出,时长为1200ms,页面栈发生push操作时该效果才生效
113  PageTransitionExit({ type: RouteType.Push, duration: 1200 })
114    .slide(SlideEffect.Left)
115  // 定义页面退出时的效果,向右侧滑出,时长为1200ms,页面栈发生pop操作时该效果才生效
116  PageTransitionExit({ type: RouteType.Pop, duration: 1200 })
117    .slide(SlideEffect.Right)
118}
119```
120
121
122以上代码则完整的定义了所有可能的页面转场样式。假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。
123
124
125| 路由操作                         | 页面A转场效果                                  | 页面B转场效果                                  |
126| ---------------------------- | ---------------------------------------- | ---------------------------------------- |
127| router.pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 |
128| router.back,从页面B返回到页面A       | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 |
129| router.pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 |
130| router.back,从页面A返回到页面B       | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 |
131
132
133>**说明:**
134>
135>    1. 由于每个页面的页面转场样式都可由开发者独立配置,而页面转场涉及到两个页面,开发者应考虑两个页面的页面转场效果的衔接,如时长尽量保持一致。
136>
137>    2. 如果没有定义匹配的页面转场样式,则该页面使用系统默认的页面转场样式。
138
139
140## 禁用某页面的页面转场
141
142
143```ts
144pageTransition() {
145  PageTransitionEnter({ type: RouteType.None, duration: 0 })
146  PageTransitionExit({ type: RouteType.None, duration: 0 })
147}
148```
149
150
151通过设置页面转场的时长为0,可使该页面无页面转场动画。
152
153
154## 场景示例
155
156下面介绍了利用[router.pushUrl](../reference/apis-arkui/js-apis-router.md#routerpushurl9)跳转能力定义了所有的四种页面转场样式的页面转场动画示例。
157
158```ts
159// PageTransitionSrc1
160@Entry
161@Component
162struct PageTransitionSrc1 {
163  build() {
164    Column() {
165      Image($r('app.media.mountain'))
166        .width('90%')
167        .height('80%')
168        .objectFit(ImageFit.Fill)
169        .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
170        .margin(30)
171
172      Row({ space: 10 }) {
173        Button("pushUrl")
174          .onClick(() => {
175            // 路由到下一个页面,push操作
176            this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst1' });
177          })
178        Button("back")
179          .onClick(() => {
180            // 返回到上一页面,相当于pop操作
181            this.getUIContext().getRouter().back();
182          })
183      }.justifyContent(FlexAlign.Center)
184    }
185    .width("100%").height("100%")
186    .alignItems(HorizontalAlign.Center)
187  }
188
189  pageTransition() {
190    // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
191    PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
192      .slide(SlideEffect.Right)
193    // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
194    PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
195      .slide(SlideEffect.Left)
196    // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
197    PageTransitionExit({ type: RouteType.Push, duration: 1000 })
198      .slide(SlideEffect.Left)
199    // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
200    PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
201      .slide(SlideEffect.Right)
202  }
203}
204```
205
206
207
208
209```ts
210// PageTransitionDst1
211@Entry
212@Component
213struct PageTransitionDst1 {
214  build() {
215    Column() {
216      Image($r('app.media.forest'))
217        .width('90%')
218        .height('80%')
219        .objectFit(ImageFit.Fill)
220        .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
221        .margin(30)
222
223      Row({ space: 10 }) {
224        Button("pushUrl")
225          .onClick(() => {
226            // 路由到下一页面,push操作
227            this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc1' });
228          })
229        Button("back")
230          .onClick(() => {
231            // 返回到上一页面,相当于pop操作
232            this.getUIContext().getRouter().back();
233          })
234      }.justifyContent(FlexAlign.Center)
235    }
236    .width("100%").height("100%")
237    .alignItems(HorizontalAlign.Center)
238  }
239
240  pageTransition() {
241    // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
242    PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
243      .slide(SlideEffect.Right)
244    // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
245    PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
246      .slide(SlideEffect.Left)
247    // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
248    PageTransitionExit({ type: RouteType.Push, duration: 1000 })
249      .slide(SlideEffect.Left)
250    // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
251    PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
252      .slide(SlideEffect.Right)
253  }
254}
255```
256
257
258
259![pageTransition_PushPop](figures/pageTransition_PushPop.gif)
260
261
262下面介绍使用了type为None的页面转场动画示例。
263
264
265
266```ts
267// PageTransitionSrc2
268@Entry
269@Component
270struct PageTransitionSrc2 {
271  build() {
272    Column() {
273      Image($r('app.media.mountain'))
274        .width('90%')
275        .height('80%')
276        .objectFit(ImageFit.Fill)
277        .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
278        .margin(30)
279
280      Row({ space: 10 }) {
281        Button("pushUrl")
282          .onClick(() => {
283            // 路由到下一页面,push操作
284            this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst2' });
285          })
286        Button("back")
287          .onClick(() => {
288            // 返回到上一页面,相当于pop操作
289            this.getUIContext().getRouter().back();
290          })
291      }.justifyContent(FlexAlign.Center)
292    }
293    .width("100%").height("100%")
294    .alignItems(HorizontalAlign.Center)
295  }
296
297  pageTransition() {
298    // 定义页面进入时的效果,从左侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效
299    PageTransitionEnter({ duration: 1000 })
300      .slide(SlideEffect.Left)
301    // 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1200ms,无论页面栈发生push还是pop操作均可生效
302    PageTransitionExit({ duration: 1200 })
303      .translate({ x: 100.0, y: 100.0 })
304      .opacity(0)
305  }
306}
307```
308
309
310
311```ts
312// PageTransitionDst2
313@Entry
314@Component
315struct PageTransitionDst2 {
316  build() {
317    Column() {
318      Image($r('app.media.forest'))
319        .width('90%')
320        .height('80%')
321        .objectFit(ImageFit.Fill)
322        .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
323        .margin(30)
324
325      Row({ space: 10 }) {
326        Button("pushUrl")
327          .onClick(() => {
328            // 路由到下一页面,push操作
329            this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc2' });
330          })
331        Button("back")
332          .onClick(() => {
333            // 返回到上一页面,相当于pop操作
334            this.getUIContext().getRouter().back();
335          })
336      }.justifyContent(FlexAlign.Center)
337    }
338    .width("100%").height("100%")
339    .alignItems(HorizontalAlign.Center)
340  }
341
342  pageTransition() {
343    // 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效
344    PageTransitionEnter({ duration: 1200 })
345      .slide(SlideEffect.Left)
346    // 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1000ms,无论页面栈发生push还是pop操作均可生效
347    PageTransitionExit({ duration: 1000 })
348      .translate({ x: 100.0, y: 100.0 })
349      .opacity(0)
350  }
351}
352```
353
354
355
356![pageTransition_None](figures/pageTransition_None.gif)
357