【鸿蒙实战开发】ArkUI转动动画-出现与消失效果实现

201 篇文章 4 订阅
201 篇文章 0 订阅

概述

转场动画是指对将要出现或消失的组件做动画,对始终出现的组件做动画应使用属性动画。转场动画主要为了让开发者从繁重的消失节点管理中解放出来,如果用属性动画做组件转场,开发者需要在动画结束回调中删除组件节点。同时,由于动画结束前已经删除的组件节点可能会重新出现,还需要在结束回调中增加对节点状态的判断。

转场动画分为基础转场和高级模板化转场,有如下几类:

  • 出现/消失转场:对新增、消失的控件实现动画效果,是通用的基础转场效果。

  • 导航转场:页面的路由转场方式,对应一个界面消失,另外一个界面出现的动画效果,如设置应用一级菜单切换到二级界面。

  • 模态转场:新的界面覆盖在旧的界面之上的动画,旧的界面不消失,新的界面出现,如弹框就是典型的模态转场动画。

  • 共享元素转场:共享元素转场是一种界面切换时对相同或者相似的元素做的一种位置和大小匹配的过渡动画效果。

  • 页面转场动画(不推荐):页面的路由转场方式,可以通过在pageTransition函数中自定义页面入场和页面退场的转场动效。为了实现更好的转场效果,推荐使用导航转场模态转场

  • 旋转屏动画增强:在原旋转屏动画基础上,可配置渐隐和渐现的转场效果。
    transition是基础的组件转场接口,用于实现一个组件出现或者消失时的动画效果。可以通过TransitionEffect的组合使用,定义出各式效果。

表1 转场效果接口

转场效果说明动画
IDENTITY禁用转场效果。无。
OPACITY默认的转场效果,透明度转场。出现时透明度从0到1,消失时透明度从1到0。
SLIDE滑动转场效果。出现时从窗口左侧滑入,消失时从窗口右侧滑出。
translate通过设置组件平移创建转场效果。出现时为translate接口设置的值到默认值0,消失时为默认值0到translate接口设置的值。
rotate通过设置组件旋转创建转场效果。出现时为rotate接口设置的值到默认值0,消失时为默认值0到rotate接口设置的值。
opacity通过设置透明度参数创建转场效果。出现时为opacity设置的值到默认透明度1,消失时为默认透明度1到opacity设置的值。
move通过TransitionEdge创建从窗口哪条边缘出来的效果。出现时从TransitionEdge方向滑入,消失时滑出到TransitionEdge方向。
asymmetric

通过此方法组合非对称的出现消失转场效果。

  • appear:出现转场的效果。

  • disappear:消失转场的效果。

| 出现时采用appear设置的TransitionEffect出现效果,消失时采用disappear设置的TransitionEffect消失效果。 |
| combine | 组合其他TransitionEffect。 | 组合其他TransitionEffect,一起生效。 |
| animation |

定义转场效果的动画参数:

  • 如果不定义会跟随animateTo的动画参数。

  • 不支持通过控件的animation接口配置动画参数。

  • TransitionEffect中animation的onFinish不生效。

| 调用顺序时从上往下,上面TransitionEffect的animation也会作用到下面TransitionEffect。 |

  1. 创建TransitionEffect。

    1.  // 出现时会是所有转场效果的出现效果叠加,消失时会是所有消失转场效果的叠加
    2.  // 用于说明各个effect跟随的动画参数
    3.  private effect: object =
    4.  TransitionEffect.OPACITY // 创建了透明度转场效果,这里没有调用animation接口,会跟随animateTo的动画参数
    5.  // 通过combine方法,添加缩放转场效果,并指定了springMotion(0.6, 1.2)曲线
    6.  .combine(TransitionEffect.scale({ x: 0, y: 0 }).animation({ curve: curves.springMotion(0.6, 1.2) }))
    7.  // 添加旋转转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 1.2)
    8.  .combine(TransitionEffect.rotate({ angle: 90 }))
    9.  // 添加平移转场效果,动画参数会跟随其之上带animation的TransitionEffect,也就是springMotion(0.6, 1.2)
    10.  .combine(TransitionEffect.translate({ x: 150, y: 150 })
    11.  // 添加move转场效果,并指定了springMotion曲线
    12.  .combine(TransitionEffect.move(TransitionEdge.END)).animation({curve: curves.springMotion()}))
    13.  // 添加非对称的转场效果,由于这里没有设置animation,会跟随上面的TransitionEffect的animation效果,也就是springMotion
    14.  .combine(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 0, y: 0 }), TransitionEffect.rotate({ angle: 90 })));

  1. 将转场效果通过transition接口设置到组件。

    1.  Text('test')
    2.  .transition(effect)
  1. 新增或者删除组件触发转场。

    1.  @State isPresent: boolean = true;
    2.  ...
    3.  if (this.isPresent) {
    4.  Text('test')
    5.  .transition(effect)
    6.  }
    7.  ...
    8.  // 控制新增或者删除组件
    9.  // 方式一:将控制变量放到animateTo闭包内,未通过animation接口定义动画参数的TransitionEffect将跟随animateTo的动画参数
    10.  animateTo({ curve: curves.springMotion() }, () => {
    11.  this.isPresent = false;
    12.  })

    14.  // 方式二:直接控制删除或者新增组件,动画参数由TransitionEffect的animation接口配置
    15.  this.isPresent = false;

完整的示例代码和效果如下,示例中采用直接删除或新增组件的方式触发转场,也可以替换为在animateTo闭包内改变控制变量触发转场。


1.  import { curves } from '@kit.ArkUI';

3.  @Entry
4.  @Component
5.  struct TransitionEffectDemo {
6.  @State isPresent: boolean = false;

8.  // 第一步,创建TransitionEffect
9.  private effect: TransitionEffect =
10.  // 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线
11.  TransitionEffect.OPACITY.animation({ curve: curves.springMotion(0.6, 0.8) })
12.  // 通过combine方法,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 0.8)
13.  .combine(TransitionEffect.scale({ x: 0, y: 0 }))
14.  // 添加旋转转场效果,这里的动画参数会跟随上面带animation的TransitionEffect,也就是springMotion(0.6, 0.8)
15.  .combine(TransitionEffect.rotate({ angle: 90 }))
16.  // 添加平移转场效果,这里的动画参数使用指定的springMotion()
17.  .combine(TransitionEffect.translate({ y: 150 }).animation({ curve: curves.springMotion() }))
18.  // 添加move转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion()
19.  .combine(TransitionEffect.move(TransitionEdge.END))

21.  build() {
22.  Stack() {
23.  if (this.isPresent) {
24.  Column() {
25.  Text('ArkUI')
26.  .fontWeight(FontWeight.Bold)
27.  .fontSize(20)
28.  .fontColor(Color.White)
29.  }
30.  .justifyContent(FlexAlign.Center)
31.  .width(150)
32.  .height(150)
33.  .borderRadius(10)
34.  .backgroundColor(0xf56c6c)
35.  // 第二步:将转场效果通过transition接口设置到组件
36.  .transition(this.effect)
37.  }

39.  // 边框
40.  Column()
41.  .width(155)
42.  .height(155)
43.  .border({
44.  width: 5,
45.  radius: 10,
46.  color: Color.Black
47.  })

49.  // 第三步:新增或者删除组件触发转场,控制新增或者删除组件
50.  Button('Click')
51.  .margin({ top: 320 })
52.  .onClick(() => {
53.  this.isPresent = !this.isPresent;
54.  })
55.  }
56.  .width('100%')
57.  .height('60%')
58.  }
59.  }

0000000000011111111.20240807205230.13583710158275855958512937567675.gif

对多个组件添加转场效果时,可以通过在animation动画参数中配置不同的delay值,实现组件渐次出现消失的效果:


1.  const ITEM_COUNTS = 9;
2.  const ITEM_COLOR = '#ED6F21';
3.  const INTERVAL = 30;
4.  const DURATION = 300;

6.  @Entry
7.  @Component
8.  struct Index1 {
9.  @State isGridShow: boolean = false;

11.  private dataArray: number[] = new Array(ITEM_COUNTS);

13.  aboutToAppear(): void {
14.  for (let i = 0; i < ITEM_COUNTS; i++) {
15.  this.dataArray[i] = i;
16.  }
17.  }

19.  build() {
20.  Stack() {
21.  if (this.isGridShow) {
22.  Grid() {
23.  ForEach(this.dataArray, (item: number, index: number) => {
24.  GridItem() {
25.  Stack() {
26.  Text((item + 1).toString())
27.  }
28.  .size({ width: 50, height: 50 })
29.  .backgroundColor(ITEM_COLOR)
30.  .transition(TransitionEffect.OPACITY
31.  .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 }))
32.  // 对每个方格的转场添加delay,实现组件的渐次出现消失效果
33.  .animation({ duration: DURATION, curve: Curve.Friction, delay: INTERVAL * index }))
34.  .borderRadius(10)
35.  }
36.  // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
37.  // 此处让方格的父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
38.  .transition(TransitionEffect.opacity(0.99))
39.  }, (item: number) => item.toString())
40.  }
41.  .columnsTemplate('1fr 1fr 1fr')
42.  .rowsGap(15)
43.  .columnsGap(15)
44.  .size({ width: 180, height: 180 })
45.  // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
46.  // 此处让父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
47.  .transition(TransitionEffect.opacity(0.99))
48.  }
49.  }
50.  .size({ width: '100%', height: '100%' })
51.  .onClick(() => {
52.  animateTo({
53.  duration: DURATION + INTERVAL * (ITEM_COUNTS - 1),
54.  curve: Curve.Friction
55.  }, () => {
56.  this.isGridShow = !this.isGridShow;
57.  })
58.  })
59.  }
60.  }

0000000000011111111.20240807205230.14511734252675133394541745533752.gif

写在最后

●如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
●更多鸿蒙最新技术知识点,请移步前往小编:https://gitee.com/

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值