1# 如何使用弹簧动画曲线 2 3## 场景说明 4在动画开发场景中,经常用到弹性效果,尤其在拖拽某个对象时经常伴随弹性动效。OpenHarmony提供了三种弹簧动画曲线用来实现弹性效果,本例将为大家介绍这三种曲线的用法。 5 6## 效果呈现 7本例最终效果如下: 8 9 10 11## 运行环境 12本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 13 14- IDE: DevEco Studio 3.1 Beta2 15- SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release) 16 17 18## 实现思路 19本例主要用到以下三种弹簧动画曲线: 20- [curves.springCurve](../application-dev/reference/apis-arkui/js-apis-curve.md#curvesspringcurve9):通过设置弹簧的初始速度、质量、刚度和阻尼来控制弹簧动画的效果。对应本例中springCurve按钮触发的动画。 21- [curves.springMotion](../application-dev/reference/apis-arkui/js-apis-curve.md#curvesspringmotion9):通过设置弹簧震动时间和阻尼来控制弹簧动画的效果。对应本例中springMotion按钮触发的动画。 22- [curves.responsiveSpringMotion](../application-dev/reference/apis-arkui/js-apis-curve.md#curvesresponsivespringmotion9):构造弹性跟手动画曲线对象,是springMotion的一种特例,仅默认参数不同,可与springMotion混合使用。用来实现拖拽动画。 23 24## 开发步骤 251. 搭建UI框架。 26样例中有两个按钮,一个图片。内容整体纵向分布,两个按钮横向分布。纵向布局可以采用Column组件,横向布局可以采用Row组件。代码如下: 27 ```ts 28 @Entry 29 @Component 30 struct ImageComponent { 31 build() { 32 Column() { 33 Row() { 34 Button('springCurve') 35 .margin({right:10}) 36 .fontSize(20) 37 .backgroundColor('#18183C') 38 Button('springMotion') 39 .fontSize(20) 40 .backgroundColor('#18183C') 41 } 42 .margin({top:30}) 43 44 Image($r("app.media.contact2")) 45 .width(100) 46 .height(100) 47 }.width("100%").height("100%").backgroundColor('#A4AE77') 48 } 49 } 50 ``` 512. 为springCurve按钮添加curves.springCurve的曲线动画。 52 ```ts 53 ... 54 // 定义状态变量translateY,用来控制笑脸图像的位移 55 @State translateY: number = 0 56 ... 57 Button('springCurve') 58 .margin({right:10}) 59 .fontSize(20) 60 .backgroundColor('#18183C') 61 // 绑定点击事件 62 .onClick(() => { 63 // 在点击事件中添加显示动画 64 animateTo({ 65 duration: 2000, 66 // 设定curves.springCurve为动画曲线 67 curve: curves.springCurve(100, 10, 80, 10) 68 }, 69 () => { 70 // 改变translateY的值,使笑脸图像发生位移 71 this.translateY = -20 72 }) 73 this.translateY = 0 74 }) 75 ... 76 Image($r("app.media.contact2")) 77 .width(100) 78 .height(100) 79 // 为笑脸图像添加位移属性,以translateY为参数 80 .translate({ y: this.translateY }) 81 ... 82 ``` 83 效果如下: 84 85  863. 为springMotion按钮添加curves.springMotion曲线动画。 87这里通过position属性控制springMotion按钮的移动,当然开发者也可以继续选择使用translate属性。 88 ```ts 89 ... 90 // 定义状态变量translateY,用来控制笑脸图像的位置变化 91 @State imgPos: { 92 x: number, 93 y: number 94 } = { x: 125, y: 400 } 95 ... 96 Button('springMotion') 97 .fontSize(20) 98 .backgroundColor('#18183C') 99 // 绑定点击事件 100 .onClick(() => { 101 // 在点击事件中添加显示动画 102 animateTo({ 103 duration: 15, 104 //设定curves.springMotion为动画曲线 105 curve: curves.springMotion(0.5, 0.5), 106 onFinish: () => { 107 animateTo({ duration: 500, 108 curve: curves.springMotion(0.5, 0.5), }, () => { 109 // 动画结束时笑脸图像位置还原 110 this.imgPos = { x: 125, y: 400 } 111 }) 112 } 113 }, () => { 114 // 改变笑脸图像位置,y轴位置由400,变为150 115 this.imgPos = { x: 125, y: 150 } 116 }) 117 }) 118 ... 119 Image($r("app.media.contact2")) 120 .width(100) 121 .height(100) 122 .translate({ y: this.translateY }) 123 // 为笑脸图像添加位置属性,以imgPos为参数 124 .position(this.imgPos) 125 ... 126 ``` 127 效果如下: 128 129  1304. 使用curves.responsiveSpringMotion为笑脸图像添加拖拽动画。 131 ```ts 132 ... 133 Image($r("app.media.contact2")) 134 .width(100) 135 .height(100) 136 .translate({ y: this.translateY }) 137 .position(this.imgPos) 138 // 绑定触摸事件 139 .onTouch((event: TouchEvent) => { 140 // 当触摸放开时,笑脸图像位置还原 141 if (event.type == TouchType.Up) { 142 animateTo({ 143 duration: 50, 144 delay: 0, 145 curve: curves.springMotion(), 146 onFinish: () => { 147 } 148 }, () => { 149 this.imgPos = { x: 125, y: 400 } 150 }) 151 } else { 152 // 触摸过程中触发跟手动画 153 animateTo({ 154 duration: 50, 155 delay: 0, 156 //设定跟手动画曲线 157 curve: curves.responsiveSpringMotion(), 158 onFinish: () => { 159 } 160 }, () => { 161 // 根据触点位置改变笑脸图像位置,从而实现跟手动画 162 this.imgPos = { 163 x: event.touches[0].screenX - 100 / 2, 164 y: event.touches[0].screenY - 100 / 2 165 } 166 }) 167 } 168 }) 169 ... 170 ``` 171 效果如下: 172 173  174 175## 完整代码 176本例完整代码如下: 177```ts 178import curves from '@ohos.curves'; 179 180@Entry 181@Component 182struct ImageComponent { 183 // 定义状态变量translateY,用来控制笑脸图像的位移 184 @State translateY: number = 0 185 // 定义状态变量translateY,用来控制笑脸图像的位置变化 186 @State imgPos: { 187 x: number, 188 y: number 189 } = { x: 125, y: 400 } 190 191 build() { 192 Column() { 193 Row() { 194 Button('springCurve') 195 .margin({right:10}) 196 .fontSize(20) 197 .backgroundColor('#18183C') 198 // 绑定点击事件 199 .onClick(() => { 200 // 在点击事件中添加显示动画 201 animateTo({ 202 duration: 2000, 203 // 设定curves.springCurve为动画曲线 204 curve: curves.springCurve(100, 10, 80, 10) 205 }, 206 () => { 207 // 改变translateY的值,使笑脸图像发生位移 208 this.translateY = -20 209 }) 210 this.translateY = 0 211 }) 212 Button('springMotion') 213 .fontSize(20) 214 .backgroundColor('#18183C') 215 // 绑定点击事件 216 .onClick(() => { 217 // 在点击事件中添加显示动画 218 animateTo({ 219 duration: 15, 220 //设定curves.springMotion为动画曲线 221 curve: curves.springMotion(0.5, 0.5), 222 onFinish: () => { 223 animateTo({ duration: 500, 224 curve: curves.springMotion(0.5, 0.5), }, () => { 225 // 动画结束时笑脸图像位置还原 226 this.imgPos = { x: 125, y: 400 } 227 }) 228 } 229 }, () => { 230 // 改变笑脸图像位置,y轴位置由400,变为150 231 this.imgPos = { x: 125, y: 150 } 232 }) 233 }) 234 } 235 .margin({top:30}) 236 237 Image($r("app.media.contact2")) 238 .width(100) 239 .height(100) 240 // 为笑脸图像添加位移属性,以translateY为参数 241 .translate({ y: this.translateY }) 242 // 为笑脸图像添加位置属性,以imgPos为参数 243 .position(this.imgPos) 244 // 绑定触摸事件 245 .onTouch((event: TouchEvent) => { 246 // 当触摸放开时,笑脸图像位置还原 247 if (event.type == TouchType.Up) { 248 animateTo({ 249 duration: 50, 250 delay: 0, 251 curve: curves.springMotion(), 252 onFinish: () => { 253 } 254 }, () => { 255 this.imgPos = { x: 125, y: 400 } 256 }) 257 } else { 258 // 触摸过程中触发跟手动画,同样通过animateTo实现动画效果 259 animateTo({ 260 duration: 50, 261 delay: 0, 262 //设定跟手动画曲线 263 curve: curves.responsiveSpringMotion(), 264 onFinish: () => { 265 } 266 }, () => { 267 // 根据触点位置改变笑脸图像位置,从而实现跟手动画 268 this.imgPos = { 269 x: event.touches[0].screenX - 100 / 2, 270 y: event.touches[0].screenY - 100 / 2 271 } 272 }) 273 } 274 }) 275 }.width("100%").height("100%").backgroundColor('#A4AE77') 276 } 277} 278``` 279## 参考 280- [显示动画](../application-dev/reference/apis-arkui/arkui-ts/ts-explicit-animation.md) 281- [插值计算](../application-dev/reference/apis-as/js-apis-curve.md)