1# 如何使用弹簧动画曲线
2
3## 场景说明
4在动画开发场景中,经常用到弹性效果,尤其在拖拽某个对象时经常伴随弹性动效。OpenHarmony提供了三种弹簧动画曲线用来实现弹性效果,本例将为大家介绍这三种曲线的用法。
5
6## 效果呈现
7本例最终效果如下:
8
9![springanimation](figures/springanimation.gif)
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    ![springCurve](figures/springCurve.gif)
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    ![springmotion](figures/springmotion.gif)
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    ![responsivemotion](figures/responsivemotion.gif)
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)