1# 帧动画 2 3通过返回应用onFrame逐帧回调的方式,让开发者在应用侧的每一帧都可以设置属性值,从而实现设置了该属性值对应组件的动画效果。接口的详细介绍请查看[@ohos.animator (动画)](../reference/apis-arkui/js-apis-animator.md)。 4 5相比于属性动画,开发者可感知动画的过程,实时修改UI侧的值,具有事件可实时响应、可暂停的优点,但性能上不如属性动画。在属性动画符合要求时更推荐使用属性动画的接口实现,可参照[实现属性动画](./arkts-attribute-animation-apis.md)。 6 7 8## 使用animator实现动画效果 9 10使用如下步骤可以创建一个简单的animator,并且在每个帧回调中打印当前插值。 11 121. 引入相关依赖。 13 14 ```ts 15 import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI'; 16 ``` 17 182. 创建执行动画的对象。 19 20 ```ts 21 // 创建动画的初始参数 22 let options: AnimatorOptions = { 23 duration: 1500, 24 easing: "friction", 25 delay: 0, 26 fill: "forwards", 27 direction: "normal", 28 iterations: 2, 29 // 动画onFrame 插值首帧值 30 begin: 200.0, 31 // 动画onFrame 插值尾帧值 32 end: 400.0 33 }; 34 let result: AnimatorResult = this.getUIContext().createAnimator(options); 35 // 设置接收到帧时回调,动画播放过程中每帧会调用onFrame回调 36 result.onFrame = (value: number) => { 37 console.log("current value is :" + value); 38 } 39 ``` 40 413. 播放动画。 42 43 ```ts 44 // 播放动画 45 result.play(); 46 ``` 47 484. 动画执行完成后手动释放AnimatorResult对象。 49 50 ```ts 51 // 释放动画对象 52 result = undefined; 53 ``` 54 55## 使用animator实现小球抛物运动 56 571. 引入相关依赖。 58 59 ```ts 60 import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI'; 61 ``` 62 632. 定义要做动画的组件。 64 65 ```ts 66 Button() 67 .width(60) 68 .height(60) 69 .translate({ x: this.translateX, y: this.translateY }) 70 ``` 71 723. 在onPageShow中创建AnimatorResult对象。 73 74 ```ts 75 onPageShow(): void { 76 //创建animatorResult对象 77 this.animatorOptions = this.getUIContext().createAnimator(options); 78 this.animatorOptions.onFrame = (progress: number) => { 79 this.translateX = progress; 80 if (progress > this.topWidth && this.translateY < this.bottomHeight) { 81 this.translateY = Math.pow(progress - this.topWidth, 2) * this.g; 82 } 83 } 84 //动画取消时执行方法 85 this.animatorOptions.onCancel = () => { 86 this.animatorStatus = '取消'; 87 } 88 //动画完成时执行方法 89 this.animatorOptions.onFinish = () => { 90 this.animatorStatus = '完成'; 91 } 92 //动画重复播放时执行方法 93 this.animatorOptions.onRepeat = () => { 94 console.log("动画重复播放"); 95 } 96 } 97 ``` 98 994. 定义动画播放,重置,暂停的按钮。 100 101 ```ts 102 Button('播放').onClick(() => { 103 this.animatorOptions?.play(); 104 this.animatorStatus = '播放中' 105 }).width(80).height(35) 106 Button("重置").onClick(() => { 107 this.translateX = 0; 108 this.translateY = 0; 109 }).width(80).height(35) 110 Button("暂停").onClick(() => { 111 this.animatorOptions?.pause(); 112 this.animatorStatus = '暂停' 113 }).width(80).height(35) 114 ``` 1155. 在页面隐藏或销毁的生命周期中释放动画对象,避免内存泄漏。 116 ```ts 117 onPageHide(): void { 118 this.animatorOptions = undefined; 119 } 120 ``` 121 122完整示例如下。 123 124```ts 125import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI'; 126 127@Entry 128@Component 129struct Index { 130 @State animatorOptions: AnimatorResult | undefined = undefined; 131 @State animatorStatus: string = '创建'; 132 begin: number = 0; 133 end: number = 300 134 topWidth: number = 150; 135 bottomHeight: number = 100; 136 g: number = 0.18 137 animatorOption: AnimatorOptions = { 138 duration: 4000, 139 delay: 0, 140 easing: 'linear', 141 iterations: 1, 142 fill: "forwards", 143 direction: 'normal', 144 begin: this.begin, 145 end: this.end 146 }; 147 @State translateX: number = 0; 148 @State translateY: number = 0; 149 150 onPageShow(): void { 151 this.animatorOptions = this.getUIContext().createAnimator(this.animatorOption) 152 this.animatorOptions.onFrame = (progress: number) => { 153 this.translateX = progress; 154 if (progress > this.topWidth && this.translateY < this.bottomHeight) { 155 this.translateY = Math.pow(progress - this.topWidth, 2) * this.g; 156 } 157 } 158 this.animatorOptions.onCancel = () => { 159 this.animatorStatus = '取消'; 160 } 161 this.animatorOptions.onFinish = () => { 162 this.animatorStatus = '完成'; 163 } 164 this.animatorOptions.onRepeat = () => { 165 console.log("动画重复播放"); 166 } 167 } 168 169 onPageHide(): void { 170 this.animatorOptions = undefined; 171 } 172 173 build() { 174 Column() { 175 Column({ space: 30 }) { 176 Button('播放').onClick(() => { 177 this.animatorOptions?.play(); 178 this.animatorStatus = '播放中'; 179 }).width(80).height(35) 180 Button("重置").onClick(() => { 181 this.translateX = 0; 182 this.translateY = 0; 183 }).width(80).height(35) 184 Button("暂停").onClick(() => { 185 this.animatorOptions?.pause(); 186 this.animatorStatus = '暂停'; 187 }).width(80).height(35) 188 }.width("100%").height('25%') 189 190 Stack() { 191 Button() 192 .width(60) 193 .height(60) 194 .translate({ x: this.translateX, y: this.translateY }) 195 } 196 .width("100%") 197 .height('45%') 198 .align(Alignment.Start) 199 200 Text("当前动画状态为:" + this.animatorStatus) 201 }.width("100%").height('100%') 202 } 203} 204``` 205 206