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.None。 39 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.Push或RouteType.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 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 357