ArkUI-属性动画

12/6/2023 ArkUI

项目案例 (opens new window)

# arkts-attribute-animation-apis.md

  • animateTo
    • 闭包内改变属性引起的界面变化,作用于出现消失转场
  • animation
    • 组件通过属性接口绑定的属性变化引起的界面变化

# 案例一

// 闭包内变量改变产生的属性动画将遵循相同的动画参数
import curves from '@ohos.curves'

@Entry
@Component
struct AnimateToDemo {
@State animate: boolean = false;
    // 第一步: 声明相关状态变量
@State rotateValue: number = 0; // 组件一旋转角度
@State translateY: number = 0; // 组件二偏移量
@State opacityValue: number = 1; // 组件二透明度

    // 第二步:将状态变量设置到相关可动画属性接口
    build() {
        Column() {
            // 组件一
            Column() {
                Text('ArkUI')
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                    .fontColor(Color.White)
            }
        .justifyContent(FlexAlign.Center)
                .width(150)
                .height(150)
                .borderRadius(10)
                .rotate({ angle: this.rotateValue })
                .backgroundColor(0xf56c6c)

            // 组件二
            Column() {
                Text('ArkUI')
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                    .fontColor(Color.White)
            }
        .justifyContent(FlexAlign.Center)
                .width(150)
                .height(150)
                .backgroundColor(0x67C23A)
                .borderRadius(10)
                .opacity(this.opacityValue)
                .translate({ y: this.translateY })

            Button('Click')
                .margin({ top: 120 })
                .onClick(() => {
                    this.animate = !this.animate;
                    // 第三步:通过属性动画接口开启属性动画
                    animateTo({ curve: curves.springMotion() }, () => {
                        // 第四步:闭包内通过状态变量改变UI界面
                        // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
                        // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画
                        this.rotateValue = this.animate ? 90 : 0;
                        // 组件二的scale属性发生变化,所以会给组件二添加scale缩放动画
                        this.opacityValue = this.animate ? 0.6 : 1;
                        // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画
                        this.translateY = this.animate ? 100 : 0;
                    })
                })
        }
    .width('100%')
            .height('100%')
            .justifyContent(FlexAlign.Center)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 案例二

// 相比于animateTo接口需要把要执行动画的属性的修改放在闭包中,animation接口无需使用闭包,把animation接口加在要做属性动画的可动画属性后即可。
// animation只要检测到其绑定的可动画属性发生变化,就会自动添加属性动画,animateTo则必须在动画闭包内改变可动画属性的值从而生成动画
import curves from '@ohos.curves';

@Entry
@Component
struct AnimationDemo {
@State animate: boolean = false;
    // 第一步: 声明相关状态变量
@State rotateValue: number = 0; // 组件一旋转角度
@State translateY: number = 0; // 组件二偏移量
@State color: Color = Color.White; // 组件二字体颜色
@State opacityValue: number = 1; // 父组件透明度

    // 第二步:将状态变量设置到相关可动画属性接口
    build() {
        Column() {
            Column() {
                // 组件一
                Text('ArkUI')
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                    .fontColor(Color.White)
                    .textAlign(TextAlign.Center)
                    .borderRadius(10)
                    .backgroundColor(0xf56c6c)
                    .rotate({ angle: this.rotateValue })
                    // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的rotate属性
                    .animation({ curve: curves.springMotion(0.3, 1.0) ,duration:3000})
                    .width(150)
                    .height(150)

                // 组件二
                Text('ArkUI')
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                    .fontColor(this.color)
                    // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的fontColor属性
                    .animation({ curve: curves.springMotion(0.6, 1.2) })
                    .textAlign(TextAlign.Center)
                    .borderRadius(10)
                    .backgroundColor(0x67C23A)
                    .width(150)
                    .height(150)
                    .translate({ y: this.translateY })
                    // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的translate属性
                    .animation({ curve: curves.springMotion(0.3, 0.6) })
            }
        .justifyContent(FlexAlign.Center)
                .opacity(this.opacityValue)
                // 这个animation会作用到上面的opacity属性,父组件column的透明度变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画
                .animation({ curve: curves.springMotion() })

            // 第四步:通过状态变量改变UI界面,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
            Button('Click')
                .margin({ top: 120 })
                .onClick(() => {
                    this.animate = !this.animate;
                    // 组件一的rotate属性有变化,所以会给组件一加rotate动画
                    this.rotateValue = this.animate ? 90 : 0;
                    // 组件二的translate属性有变化,所以会给组件二加translate动画
                    this.translateY = this.animate ? 100 : 0;
                    // 组件二的fontColor属性有变化,所以会给组件二加fontColor动画
                    this.color = this.animate ? Color.Black : Color.White;
                    // 父组件column的opacity属性有变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画
                    this.opacityValue = this.animate ? 0.6 : 1;
                })

        }
    .width('100%')
            .height('100%')
            .justifyContent(FlexAlign.Center)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Last Updated: 6/1/2024, 6:36:28 AM