1# 属性动画接口说明 2 3 4通过可动画属性改变引起UI上产生的连续视觉效果,即为属性动画。属性动画是最基础易懂的动画,ArkUI提供两种属性动画接口[animateTo](../reference/apis-arkui/arkui-ts/ts-explicit-animation.md)和[animation](../reference/apis-arkui/arkui-ts/ts-animatorproperty.md)驱动组件属性按照动画曲线等动画参数进行连续的变化,产生属性动画。 5 6 7| 属性动画接口 | 作用域 | 原理 | 使用场景 | 8| -------- | -------- | -------- | -------- | 9| animateTo | 闭包内改变属性引起的界面变化。<br/>作用于出现消失转场。 | 通用函数,对闭包前界面和闭包中的状态变量引起的界面之间的差异做动画。<br/>支持多次调用,支持嵌套。 | 适用对多个可动画属性配置相同动画参数的动画。<br/>需要嵌套使用动画的场景。 | 10| animation | 组件通过属性接口绑定的属性变化引起的界面变化。 | 识别组件的可动画属性变化,自动添加动画。<br/>组件的接口调用是从下往上执行,animation只会作用于在其之上的属性调用。<br/>组件可以根据调用顺序对多个属性设置不同的animation。 | 适用于对多个可动画属性配置不同参数动画的场景。 | 11 12## 使用animateTo产生属性动画 13 14 15``` 16animateTo(value: AnimateParam, event: () => void): void 17``` 18 19[animateTo](../reference/apis-arkui/arkui-ts/ts-explicit-animation.md)接口参数中,value指定[动画参数](../reference/apis-arkui/arkui-ts/ts-explicit-animation.md#animateparam对象说明)(包括时长、[曲线](../reference/apis-arkui/js-apis-curve.md#curve)等)event为动画的闭包函数,闭包内变量改变产生的属性动画将遵循相同的动画参数。 20 21 22```ts 23import curves from '@ohos.curves' 24 25@Entry 26@Component 27struct AnimateToDemo { 28 @State animate: boolean = false; 29 // 第一步: 声明相关状态变量 30 @State rotateValue: number = 0; // 组件一旋转角度 31 @State translateX: number = 0; // 组件二偏移量 32 @State opacityValue: number = 1; // 组件二透明度 33 34 // 第二步:将状态变量设置到相关可动画属性接口 35 build() { 36 Row() { 37 // 组件一 38 Column() { 39 } 40 .rotate({ angle: this.rotateValue }) 41 // 第三步:通过属性动画接口开启属性动画 42 .animation({ curve: curves.springMotion() }) 43 .backgroundColor('#317AF7') 44 .justifyContent(FlexAlign.Center) 45 .width(100) 46 .height(100) 47 .borderRadius(30) 48 .onClick(() => { 49 animateTo({ curve: curves.springMotion() }, () => { 50 this.animate = !this.animate; 51 // 第四步:闭包内通过状态变量改变UI界面 52 // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画 53 // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画 54 this.rotateValue = this.animate ? 90 : 0; 55 // 组件二的透明度发生变化,所以会给组件二添加透度的动画 56 this.opacityValue = this.animate ? 0.6 : 1; 57 // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画 58 this.translateX = this.animate ? 50 : 0; 59 }) 60 }) 61 62 // 组件二 63 Column() { 64 65 } 66 .justifyContent(FlexAlign.Center) 67 .width(100) 68 .height(100) 69 .backgroundColor('#D94838') 70 .borderRadius(30) 71 .opacity(this.opacityValue) 72 .translate({ x: this.translateX }) 73 } 74 .width('100%') 75 .height('100%') 76 .justifyContent(FlexAlign.Center) 77 } 78} 79``` 80 81![zh-cn_image_0000001599958466](figures/zh-cn_image_0000001599958466.gif) 82 83 84## 使用animation产生属性动画 85 86相比于animateTo接口需要把要执行动画的属性的修改放在闭包中,[animation](../reference/apis-arkui/arkui-ts/ts-animatorproperty.md)接口无需使用闭包,把animation接口加在要做属性动画的可动画属性后即可。animation只要检测到其绑定的可动画属性发生变化,就会自动添加属性动画,animateTo则必须在动画闭包内改变可动画属性的值从而生成动画。 87 88 89```ts 90import curves from '@ohos.curves' 91 92@Entry 93@Component 94struct AnimationDemo { 95 @State animate: boolean = false; 96 // 第一步: 声明相关状态变量 97 @State rotateValue: number = 0; // 组件一旋转角度 98 @State translateX: number = 0; // 组件二偏移量 99 @State opacityValue: number = 1; // 组件二透明度 100 101 // 第二步:将状态变量设置到相关可动画属性接口 102 build() { 103 Row() { 104 // 组件一 105 Column() { 106 } 107 .opacity(this.opacityValue) 108 .rotate({ angle: this.rotateValue }) 109 // 第三步:通过属性动画接口开启属性动画 110 .animation({ curve: curves.springMotion() }) 111 .backgroundColor('#317AF7') 112 .justifyContent(FlexAlign.Center) 113 .width(100) 114 .height(100) 115 .borderRadius(30) 116 .onClick(() => { 117 this.animate = !this.animate; 118 // 第四步:闭包内通过状态变量改变UI界面 119 // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画 120 // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画 121 this.rotateValue = this.animate ? 90 : 0; 122 // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画 123 this.translateX = this.animate ? 50 : 0; 124 // 父组件column的opacity属性有变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画 125 this.opacityValue = this.animate ? 0.6 : 1; 126 }) 127 128 // 组件二 129 Column() { 130 } 131 .justifyContent(FlexAlign.Center) 132 .width(100) 133 .height(100) 134 .backgroundColor('#D94838') 135 .borderRadius(30) 136 .opacity(this.opacityValue) 137 .translate({ x: this.translateX }) 138 .animation({ curve: curves.springMotion() }) 139 } 140 .width('100%') 141 .height('100%') 142 .justifyContent(FlexAlign.Center) 143 } 144} 145``` 146 147![zh-cn_image_0000001649279705](figures/zh-cn_image_0000001649279705.gif) 148 149> **说明:** 150> - 在对组件的位置大小的变化做动画的时候,由于布局属性的改变会触发测量布局,性能开销大。[scale](../reference/apis-arkui/arkui-ts/ts-universal-attributes-transformation.md)属性的改变不会触发测量布局,性能开销小。因此,在组件位置大小持续发生变化的场景,如跟手触发组件大小变化的场景,推荐适用scale。 151> 152> - 属性动画应该作用于始终存在的组件,对于将要出现或者将要消失的组件的动画应该使用[转场动画](arkts-transition-overview.md)。 153> 154> - 尽量不要使用动画结束回调。属性动画是对已经发生的状态进行的动画,不需要开发者去处理结束的逻辑。如果要使用结束回调,一定要正确处理连续操作的数据管理。 155