• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 转场动画的使用(ArkTs)
2
3## 场景介绍
4日常在应用时,经常需要衔接两个场景,或者两个镜头画面之间进行切换,切换时需要呈现一种平滑过渡效果。
5
6本例将为大家介绍下如何通过转场动画实现上述过渡效果。
7
8## 效果呈现
9本例最终效果如下:
10
11| 场景                               | 效果图                                                |
12| ---------------------------------- | ----------------------------------------------------- |
13| 页面间转场--底部滑入转场           | ![BottomTransition.gif](figures/BottomTransition.gif) |
14| 页面间转场--自定义1:缩放动画转场  | ![](figures/CustomTransition.gif)                     |
15| 页面间转场---自定义2:旋转动画转场 | ![](figures/FullCustomTransition.gif)                 |
16| 组件内转场                         | ![](figures/ComponentTransition.gif)                  |
17| 共享元素转场                       | ![](figures/SharePage.gif)                            |
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
42FullCustomTransition.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    ![Transition-animation-tree.png](figures/Transition-animation-tree.png)
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                 this.getUIContext().getRouter().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        @Entry
420        @Component
421        struct ComponentTransition {
422          @State isShow: boolean = false;
423
424          build() {
425            Column() {
426              // 页面title区域,含返回功能以及title显示
427              Row() {
428                Image($r('app.media.ic_public_back'))
429                  .width(20)
430                  .height(20)
431                  .responseRegion({
432                    width:'100%',
433                    height: '100%'
434                  })
435                  .onClick(() => {
436                    this.getUIContext().getRouter().back();
437                  })
438
439                Text($r('app.string.Component_transition_header'))
440                  .fontColor(Color.Black)
441                  .fontWeight(FontWeight.Regular)
442                  .fontSize(25)
443                  .height(300)
444                  .margin({ left:18, right:18 })
445              }
446              .height(30)
447              .width('100%')
448              .margin({ top: 20, bottom: 27,left: 24})
449
450              // 页面内容区域
451              // isShow为True,插入Image组件,同时插入动效生效;isShow为False,删除隐藏Image组件,同时删除动效生效
452              if (this.isShow) {
453                Image($r('app.media.bg_share'))
454                  .objectFit(ImageFit.Fill)
455                  .borderRadius(20)
456                  .margin({ bottom: 20 })
457                  .height(300)
458                  .width('100%')
459                    // 插入动效
460                  .transition({
461                    type: TransitionType.Insert,
462                    scale: { x: 0.5, y: 0.5 },
463                    opacity: 0
464                  })
465                    // 删除隐藏动效
466                  .transition({
467                    type: TransitionType.Delete,
468                    rotate: { x: 0, y: 1, z: 0, angle: 360 },
469                    opacity: 0
470                  })
471              }
472
473              Image($r('app.media.bg_element'))
474                .objectFit(ImageFit.Fill)
475                .borderRadius(20)
476                .margin({ bottom: 20 })
477                .width('100%')
478                .height(300)
479              Button($r('app.string.Component_transition_toggle'))
480                .height(40)
481                .width(120)
482                .fontColor(Color.White)
483                .backgroundColor($r('app.color.light_blue'))
484                .onClick(() => {
485                  animateTo({ duration: 600 }, () => {
486                    console.log('console-- ' +this.isShow)
487                    this.isShow = !this.isShow;
488                  })
489                })
490            }
491            .padding({
492              left:(20),
493              right:(20)
494            })
495            .height('100%')
496            .width('100%')
497          }
498        }
499        ```
500
501
5024. 实现元素共享转场。
503
504   共享元素转场通过给组件设置sharedTransition属性来实现,两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场效果。
505
506   * 通过Image、Column、Text等组件构建ShareItem.ets页面,给内容区域的Image组件设置sharedTransition属性标记该元素为共享元素,组件转场id设置为“shareID”, 同时设置共享元素转场效果。
507
508     具体代码如下:
509
510     ```ts
511     // entry/src/main/ets/pages/ShareItem.ets
512
513     import hilog from '@ohos.hilog';
514
515     @Entry
516     @Component
517     struct ShareItem {
518       // 自定义页面内容区域
519       @Builder PreviewArea() {
520         Column() {
521           Image($r('app.media.bg_transition'))
522             .width('100%')
523             .height(300)
524             .borderRadius(24)
525             .margin({ bottom: 12 })
526             // 设置sharedTransition属性标记该元素为共享元素,转场id为“shareId”
527             .sharedTransition('shareId', {
528               duration: 600,
529               curve: Curve.Smooth,
530               delay: 100
531             })
532
533             .onClick(() => {
534               // 路由切换
535               router.pushUrl({ url: 'pages/SharePage' })
536                 .catch(err => {
537                   hilog.error(0xFF00, '[ReadingRecorder]', `%{public}s, %{public}s`, err);
538                 });
539             })
540           Text($r('app.string.Share_Item_hint'))
541             .width('100%')
542             .textAlign(TextAlign.Center)
543             .fontSize(20)
544             .fontWeight(FontWeight.Regular)
545             .fontColor($r('app.color.share_item_content_font'))
546         }
547         .borderRadius(24)
548         .backgroundColor(Color.White)
549         .width('100%')
550         .padding({ top: 13, left: 12, right: 12,bottom:12})
551       }
552
553       build() {
554         Column() {
555           // 页面title区域,含返回功能以及title显示
556           Row() {
557             Image($r('app.media.ic_public_back'))
558               .width(20)
559               .height(20)
560               .responseRegion({
561                 width:'100%',
562                 height: '100%'
563               })
564               .onClick(() => {
565                 this.getUIContext().getRouter().back();
566               })
567
568             Text($r('app.string.Share_Item_header'))
569               .fontColor(Color.Black)
570               .fontWeight(FontWeight.Regular)
571               .fontSize(25)
572               .margin({ left:18, right:18 })
573           }
574           .height(30)
575           .width('100%')
576           .margin({ top: 20, bottom: 27,left: 24})
577           this.PreviewArea()
578         }
579         .width('100%')
580         .height('100%')
581         .backgroundColor($r('app.color.grey_light'))
582         .padding({left:12,right:12})
583       }
584     }
585     ```
586
587   * pages/SharePage.ets页面中,给Image组件设置sharedTransition属性,同时组件转场id设置为“shareID”,从而可以共享上述步骤的转场动效。
588
589        具体代码如下:
590        ```ts
591        // entry/src/main/ets/pages/SharePage.ets
592        @Entry
593        @Component
594        struct SharePage {
595            build() {
596                Column() {
597                    Image($r('app.media.bg_transition'))
598                        .objectFit(ImageFit.Fill)
599                        .width('100%')
600                        .height('100%')
601                        .sharedTransition('shareId', {
602                            duration: 600,
603                            curve: Curve.Smooth,
604                            delay: 100
605                        })
606                }
607            }
608        }
609        ```
610
611
612## 完整代码
613本例完整代码如下:
614
615应用首页: /entry/src/main/ets/pages/Index.ets616
617```ts
618// entry/src/main/ets/pages/Index.ets
619import router from '@ohos.router';
620import hilog from '@ohos.hilog';
621
622@Entry
623@Component
624struct Index {
625  build() {
626    Column() {
627      Text($r('app.string.main_page_title'))
628      .fontSize(30)
629        .fontWeight(FontWeight.Regular)
630        .width('100%')
631        .margin({ top: 13, bottom: 27,left: 24})
632
633      Scroll() {
634      	Column() {
635          ForEach(INDEX_ANIMATION_MODE, ({ imgRes , url }) => {
636            Row()
637              .backgroundImage(imgRes)
638              .backgroundImageSize(ImageSize.Cover)
639              .backgroundColor('#00000000')
640              .height(130)
641              .margin({ bottom: 30 })
642              .width('100%')
643              .borderRadius(32)
644              .onClick(() => {
645                router.pushUrl({ url: url })
646                  .catch(err => {
647                    hilog.error(0xff00, '[ReadingRecorder]', `%{public}s, %{public}s`, err);
648                  });
649              })
650          }, item => JSON.stringify(item))
651        }
652      }
653      .align(Alignment.Top)
654      .layoutWeight(1)
655      .scrollBar(BarState.Off)
656    }
657    .height('100%')
658    .backgroundColor('#F1F3F5')
659    .padding({left:12 , right:12})
660  }
661}
662```
663
664底部滑出页面:/entry/src/main/ets/pages/BottomTransition.ets665
666```ts
667// entry/src/main/ets/pages/BottomTransition.ets
668
669@Entry
670@Component
671struct BottomTransition {
672  private imgRes: string | Resource = $r('app.media.bg_transition');
673  private imgFit: ImageFit = ImageFit.Fill;
674
675  build() {
676    Column() {
677      Image(this.imgRes)
678        .objectFit(this.imgFit)
679        .width('100%')
680        .height('100%')
681    }
682
683  }
684
685  // 页面转场通过全局pageTransition方法进行配置转场参数
686  pageTransition() {
687    // PageTransitionEnter自定义入场效果:设置slide属性为SlideEffect.Bottom 表示入场时从屏幕下方滑入。
688    PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
689    // PageTransitionExit自定义出场效果:设置slide属性为SlideEffect.Bottom 退场时从屏幕下方滑出。
690    PageTransitionExit({ duration: 600, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
691  }
692}
693```
694
695自定义1 缩放动画转场页面:/entry/src/main/ets/pages/CustomTransition.ets696
697```ts
698// entry/src/main/ets/pages/CustomTransition.ets
699@Entry
700@Component
701struct CustomTransition {
702  private imgRes: string | Resource = $r('app.media.bg_transition');
703  private imgFit: ImageFit = ImageFit.Fill;
704  build() {
705    Column() {
706      Image(this.imgRes)
707        .objectFit(this.imgFit)
708        .width('100%')
709        .height('100%')
710    }
711  }
712  // 页面转场通过全局pageTransition方法进行配置转场参数
713  pageTransition() {
714    // 进场时透明度设置从0.2到1;x、y轴缩放从0变化到1
715    PageTransitionEnter({ duration: 600, curve: Curve.Smooth }).opacity(0.2).scale({ x: 0, y: 0 })
716    // 退场时x、y轴的偏移量为500
717    PageTransitionExit({ duration: 600, curve: Curve.Smooth }).translate({ x: 500, y: 500 })
718  }
719}
720```
721
722自定义2 旋转动画转场: /entry/src/main/ets/pages/FullCustomTransition.ets723
724```ts
725@Entry
726@Component
727struct FullCustomTransition {
728  @State animValue: number = 1;
729  private imgRes: string | Resource = $r('app.media.bg_transition');
730  private imgFit: ImageFit = ImageFit.Fill;
731  build() {
732    Column() {
733      Image(this.imgRes)
734        .objectFit(this.imgFit)
735        .width('100%')
736        .height('100%')
737    }
738    // 设置淡入、淡出效果
739    .opacity(this.animValue)
740    // 设置缩放
741    .scale({ x: this.animValue, y: this.animValue })
742    // 设置旋转角度
743    .rotate({
744      z: 1,
745      angle: 360 * this.animValue
746    	})
747   }
748  // 页面转场通过全局pageTransition方法进行配置转场参数
749  pageTransition() {
750    PageTransitionEnter({ duration: 600, curve: Curve.Smooth })
751      // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0 - 1)
752      .onEnter((type: RouteType, progress: number) => {
753        // 入场动效过程中,实时更新this.animValue的值
754        this.animValue = progress
755      });
756    PageTransitionExit({ duration: 600, curve: Curve.Smooth })
757      // 出场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0 - 1)
758      .onExit((type: RouteType, progress: number) => {
759        // 入场动效过程中,实时更新this.animValue的值
760         this.animValue = 1 - progress
761      });
762   }
763}
764```
765
766组件内转场页面: /entry/src/main/ets/pages/ComponentTransition.ets767
768```ts
769 @Entry
770 @Component
771 struct ComponentTransition {
772      @State isShow: boolean = false;
773      build() {
774        Column() {
775          // 页面title区域,含返回功能以及title显示
776          Row() {
777            Image($r('app.media.ic_public_back'))
778              .width(20)
779              .height(20)
780              .responseRegion({
781                width:'100%',
782                height: '100%'
783              })
784              .onClick(() => {
785                this.getUIContext().getRouter().back();
786           })
787            Text($r('app.string.Component_transition_header'))
788              .fontColor(Color.Black)
789              .fontWeight(FontWeight.Regular)
790              .fontSize(25)
791              .margin({left:18, right:18})
792          }
793          .height(30)
794          .width('100%')
795          .margin({ top: 20, bottom: 27,left: 24})
796
797          // 页面内容区域
798          // isShow为True,插入Image组件,同时插入动效生效;isShow为False,删除隐藏Image组件,同时删除动效生效
799          if (this.isShow) {
800            Image($r('app.media.bg_share'))
801              .objectFit(ImageFit.Fill)
802              .borderRadius(20)
803           	  .margin({ bottom: 20 })
804              .height(300)
805              .width('100%')
806                // 插入动效
807              .transition({
808                type: TransitionType.Insert,
809                scale: { x: 0.5, y: 0.5 },
810                opacity: 0
811              })
812                // 删除隐藏动效
813              .transition({
814                type: TransitionType.Delete,
815                rotate: { x: 0, y: 1, z: 0, angle: 360 },
816                opacity: 0
817              })
818          }
819
820
821            Image($r('app.media.bg_element'))
822              .objectFit(ImageFit.Fill)
823              .borderRadius(20)
824              .margin({ bottom: 20 })
825              .width('100%')
826              .height(300)
827
828             Button($r('app.string.Component_transition_toggle'))
829               .height(40)
830               .width(120)
831               .fontColor(Color.White)
832               .backgroundColor($r('app.color.light_blue'))
833               .onClick(() => {
834                 animateTo({ duration: 600 }, () => {
835                   this.isShow = !this.isShow;
836                 })
837               })
838           }
839           .padding({left:20,right:20})
840           .height('100%')
841           .width('100%')
842         }
843  }
844```
845
846
847共享元素转场部件:/entry/src/main/ets/pages/ShareItem.ets848
849```ts
850import hilog from '@ohos.hilog';
851
852@Entry
853@Component
854struct ShareItem {
855  // 自定义页面内容区域
856  @Builder PreviewArea() {
857    Column() {
858      Image($r('app.media.bg_transition'))
859        .width('100%')
860        .height(300)
861        .borderRadius(24)
862        .margin({ bottom: 12 })
863        // 设置sharedTransition属性标记该元素为共享元素,转场id为“shareId”
864        .sharedTransition('shareId', {
865          duration: 600,
866          curve: Curve.Smooth,
867          delay: 100
868        })
869
870        .onClick(() => {
871          // 路由切换
872          router.pushUrl({ url: 'pages/SharePage' })
873            .catch(err => {
874              hilog.error(0xFF00, '[ReadingRecorder]', `%{public}s, %{public}s`, err);
875            });
876        })
877      Text($r('app.string.Share_Item_hint'))
878        .width('100%')
879        .textAlign(TextAlign.Center)
880        .fontSize(20)
881        .fontWeight(FontWeight.Regular)
882        .fontColor($r('app.color.share_item_content_font'))
883    }
884    .borderRadius(24)
885    .backgroundColor(Color.White)
886    .width('100%')
887    .padding({ top: 13, left: 12, right: 12,bottom:12})
888  }
889
890  build() {
891    Column() {
892      // 页面title区域,含返回功能以及title显示
893      Row() {
894        Image($r('app.media.ic_public_back'))
895          .width(20)
896          .height(20)
897          .responseRegion({
898            width:'100%',
899            height: '100%'
900          })
901          .onClick(() => {
902            this.getUIContext().getRouter().back();
903          })
904
905        Text($r('app.string.Share_Item_header'))
906          .fontColor(Color.Black)
907          .fontWeight(FontWeight.Regular)
908          .fontSize(25)
909          .margin({ left:18, right:18 })
910      }
911      .height(30)
912      .width('100%')
913      .margin({ top: 20, bottom: 27,left: 24})
914      this.PreviewArea()
915    }
916    .width('100%')
917    .height('100%')
918    .backgroundColor($r('app.color.grey_light'))
919    .padding({left:12,right:12})
920  }
921}
922```
923
924共享元素转场页面:/entry/src/main/ets/pages/SharePage.ets925
926```ts
927@Entry
928@Component
929struct SharePage {
930  build() {
931    Column() {
932      Image($r('app.media.bg_transition'))
933        .objectFit(ImageFit.Fill)
934        .width('100%')
935        .height('100%')
936        .sharedTransition('shareId', {
937          duration: 600,
938          curve: Curve.Smooth,
939          delay: 100
940        })
941    }
942  }
943}
944```
945
946 ##  参考
947
948- [图形变换](../application-dev/reference/apis-arkui/arkui-ts/ts-universal-attributes-transformation.md)
949
950- [页面间转场](../application-dev/reference/apis-arkui/arkui-ts/ts-page-transition-animation.md)
951
952- [组件内转场](../application-dev/ui/arkts-shared-element-transition.md)
953
954- [共享元素转场](../application-dev/reference/apis-arkui/arkui-ts/ts-transition-animation-shared-elements.md)
955
956
957