1# 转场动画的使用(ArkTs) 2 3## 场景介绍 4日常在应用时,经常需要衔接两个场景,或者两个镜头画面之间进行切换,切换时需要呈现一种平滑过渡效果。 5 6本例将为大家介绍下如何通过转场动画实现上述过渡效果。 7 8## 效果呈现 9本例最终效果如下: 10 11| 场景 | 效果图 | 12| ---------------------------------- | ----------------------------------------------------- | 13| 页面间转场--底部滑入转场 |  | 14| 页面间转场--自定义1:缩放动画转场 |  | 15| 页面间转场---自定义2:旋转动画转场 |  | 16| 组件内转场 |  | 17| 共享元素转场 |  | 18 19 20 21## 运行环境 22本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 23- IDE: DevEco Studio 4.0 Beta1 24- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1) 25## 实现思路 26* 构建应用首页,主要由5个相同样式的功能菜单组成,通过添加路由实现主页面与对应功能页面的链接跳转。 27 28* 功能页面的实现 29 30 * 页面间转场 31 32 * 底部滑入转场 33 34 通过给pageTransition()方法定义入场效果PageTransitionEnter以及出场效果PageTransitionExit,同时通过设置slide属性为SlideEffect.Bottom来实现从底部滑入动效。 35 36 * 缩放动画转场 37 38 通过设置pageTransition方法,配置进行配置转场参数。 39 40 * 旋转动画转场 41 42 在FullCustomTransition.ets的Column组件中添加TransitionElement组件,并且定义pageTransition方法。给Clomn组件添加opacity、scale、rotate属性,定义变量animValue用来控制Clomn组件的动效,在PageTransitionEnter和PageTransitionExit组件中动态改变myProgress的值,从而控制动画效果。 43 44 * 组件间转场 45 46 * 通过Image、Column、Text、Button等组件构建ComponentTransition.ets页面。 47 48 * 新建一个Image组件,并且添加两个transition属性,分别用于定义组件的插入动效和移除动效,从而实现组件间的转场。 49 50 * 设置变量isShow,用来控制上述步骤中Image组件的添加和移除,同时向Button组件的onClick添加animateTo方法,来使ComponentItem子组件动效生效。 51 * isShow默认状态为false,删除隐藏Image组件,同时删除动效生效。 52 53 * 当isShow状态更新为true时,插入Image组件,同时插入动效生效。 54 55 * 共享转场 56 57 通过给两个页面“SharedItem”和“SharePage” 的Image组件设置sharedTransition属性来实现,两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场效果。 58 59## 开发步骤 601. 创建主界面。 61 62 添加媒体资源至resources > base > media目录下。 63 64  65 66 首页Index.ets引入首页列表常量数据:INDEX_ANIMATION_MODE(imgRes:设置按钮的背景图片,url:设置页面路由的地址),通过ForEach方法循环渲染列表常量数据。 67 具体代码如下: 68 69 ```ts 70 // entry/src/main/ets/pages/Index.ets 71 72 // 引入列表常量数据INDEX_ANIMATION_MODE 73 export const INDEX_ANIMATION_MODE = [ 74 { imgRes: $r('app.media.bg_bottom_anim_transition'), url: 'pages/BottomTransition' }, 75 { imgRes: $r('app.media.bg_custom1_anim_transition'), url: 'pages/CustomTransition' }, 76 { imgRes: $r('app.media.bg_custom2_anim_transition'), url: 'pages/FullCustomTransition' }, 77 { imgRes: $r('app.media.bg_element_anim_transition'), url: 'pages/ComponentTransition' }, 78 { imgRes: $r('app.media.bg_share_anim_transition'), url: 'pages/ShareItem' } 79 ]; 80 81 ... 82 Column() { 83 // ForEach循环渲染 84 ForEach(INDEX_ANIMATION_MODE, ({ imgRes , url }) => { 85 Row() 86 .backgroundImage(imgRes) 87 .backgroundImageSize(ImageSize.Cover) 88 .backgroundColor('#00000000') 89 .height(130) 90 .margin({ bottom: 30 }) 91 .width('100%') 92 .borderRadius(32) 93 .onClick(() => { 94 router.pushUrl({ url: url }) 95 }) 96 }, item => JSON.stringify(item)) 97 } 98 ``` 99 100 添加其它组件,以及样式,完成UI构建。 101 102 具体代码如下: 103 ```ts 104 // entry/src/main/ets/pages/Index.ets 105 import router from '@ohos.router'; 106 import hilog from '@ohos.hilog'; 107 @Entry 108 @Component 109 struct Index { 110 build() { 111 Column() { 112 Text($r('app.string.main_page_title')) 113 .fontSize(30) 114 .fontWeight(FontWeight.Regular) 115 .width('100%') 116 .margin({ top: 13, bottom: 27,left: 24}) 117 118 Scroll() { 119 Column() { 120 ForEach(INDEX_ANIMATION_MODE, ({ imgRes , url }) => { 121 Row() 122 .backgroundImage(imgRes) 123 .backgroundImageSize(ImageSize.Cover) 124 .backgroundColor('#00000000') 125 .height(130) 126 .margin({ bottom: 30 }) 127 .width('100%') 128 .borderRadius(32) 129 .onClick(() => { 130 router.pushUrl({ url: url }) 131 .catch(err => { 132 hilog.error(0xff00, '[ReadingRecorder]', `%{public}s, %{public}s`, err); 133 }); 134 }) 135 }, item => JSON.stringify(item)) 136 } 137 } 138 .align(Alignment.Top) 139 .layoutWeight(1) 140 .scrollBar(BarState.Off) 141 } 142 .height('100%') 143 .backgroundColor('#F1F3F5') 144 .padding({left:12 , right:12}) 145 } 146 } 147 ``` 148 1492. 实现页面间转场。 150 * 效果1:底部滑入。 151 152 该效果的实现,主要是通过在BottomTransition.ets中设置全局pageTransition()方法,该方法中自定义入场效果PageTransitionEnter以及出场效果PageTransitionExit,同时通过设置slide属性为SlideEffect.Bottom来实现从底部滑入动效。 153 154 具体代码如下: 155 156 ```ts 157 // entry/src/main/ets/pages/BottomTransition.ets 158 159 @Entry 160 @Component 161 struct BottomTransition { 162 private imgRes: string | Resource = $r('app.media.bg_transition'); 163 private imgFit: ImageFit = ImageFit.Fill; 164 165 build() { 166 Column() { 167 Image(this.imgRes) 168 .objectFit(this.imgFit) 169 .width('100%') 170 .height('100%') 171 } 172 173 } 174 175 // 页面转场通过全局pageTransition方法进行配置转场参数 176 pageTransition() { 177 // PageTransitionEnter自定义入场效果:设置slide属性为SlideEffect.Bottom 表示入场时从屏幕下方滑入。 178 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom); 179 // PageTransitionExit自定义出场效果:设置slide属性为SlideEffect.Bottom 退场时从屏幕下方滑出。 180 PageTransitionExit({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom); 181 } 182 } 183 184 ``` 185 186 * 效果2:页面入场时淡入和放大,退场时从右下角滑出。 187 188 * 在CustomTransition.ets中设置全局pageTransition()方法。 189 * pageTransition方法中自定义入场效果PageTransitionEnter:透明度设置从0.2到1;x、y轴缩放从0变化到1。 190 * pageTransition方法中自定义出场效果PageTransitionExit: x、y轴的偏移量为500。 191 192 具体代码如下: 193 194 ```ts 195 // entry/src/main/ets/pages/CustomTransition.ets 196 197 @Entry 198 @Component 199 struct CustomTransition { 200 private imgRes: string | Resource = $r('app.media.bg_transition'); 201 private imgFit: ImageFit = ImageFit.Fill; 202 203 build() { 204 Column() { 205 Image(this.imgRes) 206 .objectFit(this.imgFit) 207 .width('100%') 208 .height('100%') 209 } 210 } 211 212 // 页面转场通过全局pageTransition方法进行配置转场参数 213 pageTransition() { 214 // 进场时透明度设置从0.2到1;x、y轴缩放从0变化到1 215 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).opacity(0.2).scale({ x: 0, y: 0 }) 216 // 退场时x、y轴的偏移量为500 217 PageTransitionExit({ duration: 600, curve: Curve.Smooth }).translate({ x: 500, y: 500 }) 218 } 219 } 220 ``` 221 222 * 效果3:页面入场时淡入和放大,同时顺时针旋转;退场时淡出和缩小,同时逆时针旋转。 223 224 * 在FullCustomTransition.ets中添加Column组件。 225 226 * 向Column组件添加属性:opacity、scale、rotate,来控制动效的淡入淡出、缩放以及旋转效果。 227 228 * 定义变量animValue用来,通过animValue值得变化来控制Column组件的动效。 229 * 在FullCustomTransition.ets中定义全局pageTransition()方法。 230 * pageTransition方法中自定义入场效果PageTransitionEnter。 231 232 animValue值实时变化,0 --> 1,从而渲染 入场时淡入、放大以及顺时针旋转效果。 233 * pageTransition方法中自定义出场效果PageTransitionExit。 234 235 animValue值实时变化,1 --> 0,从而渲染 出场时淡出、缩小以及逆时针旋转效果。 236 237 具体代码如下: 238 239 ```ts 240 // entry/src/main/ets/pages/FullCustomTransition.ets 241 242 @Entry 243 @Component 244 struct FullCustomTransition { 245 @State animValue: number = 1; 246 private imgRes: string | Resource = $r('app.media.bg_transition'); 247 private imgFit: ImageFit = ImageFit.Fill; 248 249 build() { 250 Column() { 251 Image(this.imgRes) 252 .objectFit(this.imgFit) 253 .width('100%') 254 .height('100%') 255 } 256 // 设置淡入、淡出效果 257 .opacity(this.animValue) 258 // 设置缩放 259 .scale({ x: this.animValue, y: this.animValue }) 260 // 设置旋转角度 261 .rotate({ 262 z: 1, 263 angle: 360 * this.animValue 264 }) 265 } 266 267 // 页面转场通过全局pageTransition方法进行配置转场参数 268 pageTransition() { 269 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }) 270 // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0 - 1) 271 .onEnter((type: RouteType, progress: number) => { 272 // 入场动效过程中,实时更新this.animValue的值 273 this.animValue = progress 274 }); 275 PageTransitionExit({ duration: 600, curve: Curve.Smooth }) 276 // 出场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0 - 1) 277 .onExit((type: RouteType, progress: number) => { 278 // 入场动效过程中,实时更新this.animValue的值 279 this.animValue = 1 - progress 280 }); 281 } 282 } 283 ``` 284 285 2863. 实现组件内转场。 287 288 * 通过Image、Column、Text、Button等组件构建ComponentTransition.ets页面。 289 290 具体代码如下: 291 292 ```ts 293 // entry/src/main/ets/pages/ComponentTransition.ets 294 295 @Entry 296 @Component 297 struct ComponentTransition { 298 299 build() { 300 Column() { 301 Row() { 302 Image($r('app.media.ic_public_back')) 303 .width(20) 304 .height(20) 305 .responseRegion({width:'100%',height: '100%'}) 306 .onClick(() => { 307 router.back(); 308 }) 309 310 Text($r('app.string.Component_transition_header')) 311 .fontColor(Color.Black) 312 .fontWeight(FontWeight.Regular) 313 .fontSize(25) 314 .margin({left:18,right:18}) 315 } 316 .height(30) 317 .width('100%') 318 .margin({ top: 20, bottom: 27,left: 24}) 319 320 321 Image($r('app.media.bg_element')) 322 .objectFit(ImageFit.Fill) 323 .borderRadius(20) 324 .margin({ bottom: 20 }) 325 .width('100%') 326 .height(300) 327 328 Button($r('app.string.Component_transition_toggle')) 329 .height(40) 330 .width(120) 331 .fontColor(Color.White) 332 .backgroundColor($r('app.color.light_blue')) 333 } 334 .padding({left:20,right:20}) 335 .height('100%') 336 .width('100%') 337 } 338 } 339 340 ``` 341 342 * 新建一个Image组件,并且添加两个transition属性,分别用于定义组件的插入动效和移除动效,来实现组件转场间。 343 344 具体代码如下: 345 346 ```ts 347 // entry/src/main/ets/pages/ComponentTransition.ets 348 ... 349 Image($r('app.media.bg_share')) 350 .objectFit(ImageFit.Fill) 351 .borderRadius(20) 352 .margin({ bottom: 20 }) 353 .height(300) 354 .width('100%') 355 // 插入动效 356 .transition({ 357 type: TransitionType.Insert, 358 scale: { x: 0.5, y: 0.5 }, 359 opacity: 0 360 }) 361 // 删除隐藏动效 362 .transition({ 363 type: TransitionType.Delete, 364 rotate: { x: 0, y: 1, z: 0, angle: 360 }, 365 opacity: 0 366 }) 367 ``` 368 369 370 - 设置变量isShow,用来控制上述步骤中Image组件的添加和移除,同时向Button组件的onClick添加animateTo方法,来使ComponentItem子组件动效生效。 371 372 * isShow默认状态为false,删除隐藏Image组件,同时删除动效生效。 373 374 * 当isShow状态更新为true时,插入Image组件,同时插入动效生效。 375 376 具体代码如下: 377 378 ```ts 379 // entry/src/main/ets/pages/ComponentTransition.ets 380 381 ... 382 @State isShow: boolean = false; 383 ... 384 // isShow为True,插入Image组件,同时插入动效生效;isShow为False,删除隐藏Image组件,同时删除动效生效 385 if (this.isShow) { 386 Image($r('app.media.bg_share')) 387 .objectFit(ImageFit.Fill) 388 .borderRadius(20) 389 .margin({ bottom: 20 }) 390 .height(300) 391 .width('100%') 392 // 插入动效 393 .transition({ 394 type: TransitionType.Insert, 395 scale: { x: 0.5, y: 0.5 }, 396 opacity: 0 397 }) 398 // 删除隐藏动效 399 .transition({ 400 type: TransitionType.Delete, 401 rotate: { x: 0, y: 1, z: 0, angle: 360 }, 402 opacity: 0 403 }) 404 } 405 ... 406 Button($r('app.string.Component_transition_toggle')) 407 ... 408 .onClick(() => { 409 animateTo({ duration: 600 }, () => { 410 this.isShow = !this.isShow; 411 }) 412 }) 413 ``` 414 415 ComponentTransition.ets的完整代码如下: 416 417 ```ts 418 // entry/src/main/ets/pages/ComponentTransition.ets 419 import router from '@ohos.router'; 420 421 @Entry 422 @Component 423 struct ComponentTransition { 424 @State isShow: boolean = false; 425 426 build() { 427 Column() { 428 // 页面title区域,含返回功能以及title显示 429 Row() { 430 Image($r('app.media.ic_public_back')) 431 .width(20) 432 .height(20) 433 .responseRegion({ 434 width:'100%', 435 height: '100%' 436 }) 437 .onClick(() => { 438 router.back(); 439 }) 440 441 Text($r('app.string.Component_transition_header')) 442 .fontColor(Color.Black) 443 .fontWeight(FontWeight.Regular) 444 .fontSize(25) 445 .height(300) 446 .margin({ left:18, right:18 }) 447 } 448 .height(30) 449 .width('100%') 450 .margin({ top: 20, bottom: 27,left: 24}) 451 452 // 页面内容区域 453 // isShow为True,插入Image组件,同时插入动效生效;isShow为False,删除隐藏Image组件,同时删除动效生效 454 if (this.isShow) { 455 Image($r('app.media.bg_share')) 456 .objectFit(ImageFit.Fill) 457 .borderRadius(20) 458 .margin({ bottom: 20 }) 459 .height(300) 460 .width('100%') 461 // 插入动效 462 .transition({ 463 type: TransitionType.Insert, 464 scale: { x: 0.5, y: 0.5 }, 465 opacity: 0 466 }) 467 // 删除隐藏动效 468 .transition({ 469 type: TransitionType.Delete, 470 rotate: { x: 0, y: 1, z: 0, angle: 360 }, 471 opacity: 0 472 }) 473 } 474 475 Image($r('app.media.bg_element')) 476 .objectFit(ImageFit.Fill) 477 .borderRadius(20) 478 .margin({ bottom: 20 }) 479 .width('100%') 480 .height(300) 481 Button($r('app.string.Component_transition_toggle')) 482 .height(40) 483 .width(120) 484 .fontColor(Color.White) 485 .backgroundColor($r('app.color.light_blue')) 486 .onClick(() => { 487 animateTo({ duration: 600 }, () => { 488 console.log('console-- ' +this.isShow) 489 this.isShow = !this.isShow; 490 }) 491 }) 492 } 493 .padding({ 494 left:(20), 495 right:(20) 496 }) 497 .height('100%') 498 .width('100%') 499 } 500 } 501 ``` 502 503 5044. 实现元素共享转场。 505 506 共享元素转场通过给组件设置sharedTransition属性来实现,两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场效果。 507 508 * 通过Image、Column、Text等组件构建ShareItem.ets页面,给内容区域的Image组件设置sharedTransition属性标记该元素为共享元素,组件转场id设置为“shareID”, 同时设置共享元素转场效果。 509 510 具体代码如下: 511 512 ```ts 513 // entry/src/main/ets/pages/ShareItem.ets 514 515 import hilog from '@ohos.hilog'; 516 517 @Entry 518 @Component 519 struct ShareItem { 520 // 自定义页面内容区域 521 @Builder PreviewArea() { 522 Column() { 523 Image($r('app.media.bg_transition')) 524 .width('100%') 525 .height(300) 526 .borderRadius(24) 527 .margin({ bottom: 12 }) 528 // 设置sharedTransition属性标记该元素为共享元素,转场id为“shareId” 529 .sharedTransition('shareId', { 530 duration: 600, 531 curve: Curve.Smooth, 532 delay: 100 533 }) 534 535 .onClick(() => { 536 // 路由切换 537 router.pushUrl({ url: 'pages/SharePage' }) 538 .catch(err => { 539 hilog.error(0xFF00, '[ReadingRecorder]', `%{public}s, %{public}s`, err); 540 }); 541 }) 542 Text($r('app.string.Share_Item_hint')) 543 .width('100%') 544 .textAlign(TextAlign.Center) 545 .fontSize(20) 546 .fontWeight(FontWeight.Regular) 547 .fontColor($r('app.color.share_item_content_font')) 548 } 549 .borderRadius(24) 550 .backgroundColor(Color.White) 551 .width('100%') 552 .padding({ top: 13, left: 12, right: 12,bottom:12}) 553 } 554 555 build() { 556 Column() { 557 // 页面title区域,含返回功能以及title显示 558 Row() { 559 Image($r('app.media.ic_public_back')) 560 .width(20) 561 .height(20) 562 .responseRegion({ 563 width:'100%', 564 height: '100%' 565 }) 566 .onClick(() => { 567 router.back(); 568 }) 569 570 Text($r('app.string.Share_Item_header')) 571 .fontColor(Color.Black) 572 .fontWeight(FontWeight.Regular) 573 .fontSize(25) 574 .margin({ left:18, right:18 }) 575 } 576 .height(30) 577 .width('100%') 578 .margin({ top: 20, bottom: 27,left: 24}) 579 this.PreviewArea() 580 } 581 .width('100%') 582 .height('100%') 583 .backgroundColor($r('app.color.grey_light')) 584 .padding({left:12,right:12}) 585 } 586 } 587 ``` 588 589 * pages/SharePage.ets页面中,给Image组件设置sharedTransition属性,同时组件转场id设置为“shareID”,从而可以共享上述步骤的转场动效。 590 591 具体代码如下: 592 ```ts 593 // entry/src/main/ets/pages/SharePage.ets 594 @Entry 595 @Component 596 struct SharePage { 597 build() { 598 Column() { 599 Image($r('app.media.bg_transition')) 600 .objectFit(ImageFit.Fill) 601 .width('100%') 602 .height('100%') 603 .sharedTransition('shareId', { 604 duration: 600, 605 curve: Curve.Smooth, 606 delay: 100 607 }) 608 } 609 } 610 } 611 ``` 612 613 614## 完整代码 615本例完整代码如下: 616 617应用首页: /entry/src/main/ets/pages/Index.ets。 618 619```ts 620// entry/src/main/ets/pages/Index.ets 621import router from '@ohos.router'; 622import hilog from '@ohos.hilog'; 623 624@Entry 625@Component 626struct Index { 627 build() { 628 Column() { 629 Text($r('app.string.main_page_title')) 630 .fontSize(30) 631 .fontWeight(FontWeight.Regular) 632 .width('100%') 633 .margin({ top: 13, bottom: 27,left: 24}) 634 635 Scroll() { 636 Column() { 637 ForEach(INDEX_ANIMATION_MODE, ({ imgRes , url }) => { 638 Row() 639 .backgroundImage(imgRes) 640 .backgroundImageSize(ImageSize.Cover) 641 .backgroundColor('#00000000') 642 .height(130) 643 .margin({ bottom: 30 }) 644 .width('100%') 645 .borderRadius(32) 646 .onClick(() => { 647 router.pushUrl({ url: url }) 648 .catch(err => { 649 hilog.error(0xff00, '[ReadingRecorder]', `%{public}s, %{public}s`, err); 650 }); 651 }) 652 }, item => JSON.stringify(item)) 653 } 654 } 655 .align(Alignment.Top) 656 .layoutWeight(1) 657 .scrollBar(BarState.Off) 658 } 659 .height('100%') 660 .backgroundColor('#F1F3F5') 661 .padding({left:12 , right:12}) 662 } 663} 664``` 665 666底部滑出页面:/entry/src/main/ets/pages/BottomTransition.ets。 667 668```ts 669// entry/src/main/ets/pages/BottomTransition.ets 670 671@Entry 672@Component 673struct BottomTransition { 674 private imgRes: string | Resource = $r('app.media.bg_transition'); 675 private imgFit: ImageFit = ImageFit.Fill; 676 677 build() { 678 Column() { 679 Image(this.imgRes) 680 .objectFit(this.imgFit) 681 .width('100%') 682 .height('100%') 683 } 684 685 } 686 687 // 页面转场通过全局pageTransition方法进行配置转场参数 688 pageTransition() { 689 // PageTransitionEnter自定义入场效果:设置slide属性为SlideEffect.Bottom 表示入场时从屏幕下方滑入。 690 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom); 691 // PageTransitionExit自定义出场效果:设置slide属性为SlideEffect.Bottom 退场时从屏幕下方滑出。 692 PageTransitionExit({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom); 693 } 694} 695``` 696 697自定义1 缩放动画转场页面:/entry/src/main/ets/pages/CustomTransition.ets。 698 699```ts 700// entry/src/main/ets/pages/CustomTransition.ets 701@Entry 702@Component 703struct CustomTransition { 704 private imgRes: string | Resource = $r('app.media.bg_transition'); 705 private imgFit: ImageFit = ImageFit.Fill; 706 build() { 707 Column() { 708 Image(this.imgRes) 709 .objectFit(this.imgFit) 710 .width('100%') 711 .height('100%') 712 } 713 } 714 // 页面转场通过全局pageTransition方法进行配置转场参数 715 pageTransition() { 716 // 进场时透明度设置从0.2到1;x、y轴缩放从0变化到1 717 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).opacity(0.2).scale({ x: 0, y: 0 }) 718 // 退场时x、y轴的偏移量为500 719 PageTransitionExit({ duration: 600, curve: Curve.Smooth }).translate({ x: 500, y: 500 }) 720 } 721} 722``` 723 724自定义2 旋转动画转场: /entry/src/main/ets/pages/FullCustomTransition.ets。 725 726```ts 727@Entry 728@Component 729struct FullCustomTransition { 730 @State animValue: number = 1; 731 private imgRes: string | Resource = $r('app.media.bg_transition'); 732 private imgFit: ImageFit = ImageFit.Fill; 733 build() { 734 Column() { 735 Image(this.imgRes) 736 .objectFit(this.imgFit) 737 .width('100%') 738 .height('100%') 739 } 740 // 设置淡入、淡出效果 741 .opacity(this.animValue) 742 // 设置缩放 743 .scale({ x: this.animValue, y: this.animValue }) 744 // 设置旋转角度 745 .rotate({ 746 z: 1, 747 angle: 360 * this.animValue 748 }) 749 } 750 // 页面转场通过全局pageTransition方法进行配置转场参数 751 pageTransition() { 752 PageTransitionEnter({ duration: 600, curve: Curve.Smooth }) 753 // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0 - 1) 754 .onEnter((type: RouteType, progress: number) => { 755 // 入场动效过程中,实时更新this.animValue的值 756 this.animValue = progress 757 }); 758 PageTransitionExit({ duration: 600, curve: Curve.Smooth }) 759 // 出场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0 - 1) 760 .onExit((type: RouteType, progress: number) => { 761 // 入场动效过程中,实时更新this.animValue的值 762 this.animValue = 1 - progress 763 }); 764 } 765} 766``` 767 768组件内转场页面: /entry/src/main/ets/pages/ComponentTransition.ets。 769 770```ts 771 import router from '@ohos.router'; 772 @Entry 773 @Component 774 struct ComponentTransition { 775 @State isShow: boolean = false; 776 build() { 777 Column() { 778 // 页面title区域,含返回功能以及title显示 779 Row() { 780 Image($r('app.media.ic_public_back')) 781 .width(20) 782 .height(20) 783 .responseRegion({ 784 width:'100%', 785 height: '100%' 786 }) 787 .onClick(() => { 788 router.back(); 789 }) 790 Text($r('app.string.Component_transition_header')) 791 .fontColor(Color.Black) 792 .fontWeight(FontWeight.Regular) 793 .fontSize(25) 794 .margin({left:18, right:18}) 795 } 796 .height(30) 797 .width('100%') 798 .margin({ top: 20, bottom: 27,left: 24}) 799 800 // 页面内容区域 801 // isShow为True,插入Image组件,同时插入动效生效;isShow为False,删除隐藏Image组件,同时删除动效生效 802 if (this.isShow) { 803 Image($r('app.media.bg_share')) 804 .objectFit(ImageFit.Fill) 805 .borderRadius(20) 806 .margin({ bottom: 20 }) 807 .height(300) 808 .width('100%') 809 // 插入动效 810 .transition({ 811 type: TransitionType.Insert, 812 scale: { x: 0.5, y: 0.5 }, 813 opacity: 0 814 }) 815 // 删除隐藏动效 816 .transition({ 817 type: TransitionType.Delete, 818 rotate: { x: 0, y: 1, z: 0, angle: 360 }, 819 opacity: 0 820 }) 821 } 822 823 824 Image($r('app.media.bg_element')) 825 .objectFit(ImageFit.Fill) 826 .borderRadius(20) 827 .margin({ bottom: 20 }) 828 .width('100%') 829 .height(300) 830 831 Button($r('app.string.Component_transition_toggle')) 832 .height(40) 833 .width(120) 834 .fontColor(Color.White) 835 .backgroundColor($r('app.color.light_blue')) 836 .onClick(() => { 837 animateTo({ duration: 600 }, () => { 838 this.isShow = !this.isShow; 839 }) 840 }) 841 } 842 .padding({left:20,right:20}) 843 .height('100%') 844 .width('100%') 845 } 846 } 847``` 848 849 850共享元素转场部件:/entry/src/main/ets/pages/ShareItem.ets。 851 852```ts 853import hilog from '@ohos.hilog'; 854 855@Entry 856@Component 857struct ShareItem { 858 // 自定义页面内容区域 859 @Builder PreviewArea() { 860 Column() { 861 Image($r('app.media.bg_transition')) 862 .width('100%') 863 .height(300) 864 .borderRadius(24) 865 .margin({ bottom: 12 }) 866 // 设置sharedTransition属性标记该元素为共享元素,转场id为“shareId” 867 .sharedTransition('shareId', { 868 duration: 600, 869 curve: Curve.Smooth, 870 delay: 100 871 }) 872 873 .onClick(() => { 874 // 路由切换 875 router.pushUrl({ url: 'pages/SharePage' }) 876 .catch(err => { 877 hilog.error(0xFF00, '[ReadingRecorder]', `%{public}s, %{public}s`, err); 878 }); 879 }) 880 Text($r('app.string.Share_Item_hint')) 881 .width('100%') 882 .textAlign(TextAlign.Center) 883 .fontSize(20) 884 .fontWeight(FontWeight.Regular) 885 .fontColor($r('app.color.share_item_content_font')) 886 } 887 .borderRadius(24) 888 .backgroundColor(Color.White) 889 .width('100%') 890 .padding({ top: 13, left: 12, right: 12,bottom:12}) 891 } 892 893 build() { 894 Column() { 895 // 页面title区域,含返回功能以及title显示 896 Row() { 897 Image($r('app.media.ic_public_back')) 898 .width(20) 899 .height(20) 900 .responseRegion({ 901 width:'100%', 902 height: '100%' 903 }) 904 .onClick(() => { 905 router.back(); 906 }) 907 908 Text($r('app.string.Share_Item_header')) 909 .fontColor(Color.Black) 910 .fontWeight(FontWeight.Regular) 911 .fontSize(25) 912 .margin({ left:18, right:18 }) 913 } 914 .height(30) 915 .width('100%') 916 .margin({ top: 20, bottom: 27,left: 24}) 917 this.PreviewArea() 918 } 919 .width('100%') 920 .height('100%') 921 .backgroundColor($r('app.color.grey_light')) 922 .padding({left:12,right:12}) 923 } 924} 925``` 926 927共享元素转场页面:/entry/src/main/ets/pages/SharePage.ets。 928 929```ts 930@Entry 931@Component 932struct SharePage { 933 build() { 934 Column() { 935 Image($r('app.media.bg_transition')) 936 .objectFit(ImageFit.Fill) 937 .width('100%') 938 .height('100%') 939 .sharedTransition('shareId', { 940 duration: 600, 941 curve: Curve.Smooth, 942 delay: 100 943 }) 944 } 945 } 946} 947``` 948 949 ## 参考 950 951- [图形变换](../application-dev/reference/apis-arkui/arkui-ts/ts-universal-attributes-transformation.md) 952 953- [页面间转场](../application-dev/reference/apis-arkui/arkui-ts/ts-page-transition-animation.md) 954 955- [组件内转场](../application-dev/ui/arkts-shared-element-transition.md) 956 957- [共享元素转场](../application-dev/reference/apis-arkui/arkui-ts/ts-transition-animation-shared-elements.md) 958 959 960