1e41f4b71Sopenharmony_ci# Spring Curve
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciIn a damped spring system corresponding to a damped spring curve (spring curve for short), an object that deviates from the equilibrium position is forced to oscillate due to a reverse force generated by spring deformation; this oscillation is resisted by the damping force. Except for the special case where the damping is 0, the oscillation gradually decays in amplitude towards 0, and the resultant animation curve is natural and continuous.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciAn animation using the spring curve slows down toward the end until the velocity is 0, instead of stopping abruptly.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ciArkUI provides four types of damped spring curve APIs:
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci- [springMotion](../reference/apis/js-apis-curve.md#curvesspringmotion9): creates a spring animation curve. The animation duration is automatically calculated based on the curve parameters, attribute change values, and initial spring velocity. Manually set animation duration values do not take effect.
14e41f4b71Sopenharmony_ci    **springMotion** does not provide any API for setting the velocity, as the velocity is obtained through inheritance. For an attribute, if there is already a springMotion or responsiveSpringMotion animation running, a new spring animation will stop the running animation and inherit the attribute values and velocity of that animation as its initial values. This spring curve API provides default parameters, which you can directly use when appropriate.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci  ```ts
17e41f4b71Sopenharmony_ci  function springMotion(response?: number, dampingFraction?: number, overlapDuration?: number): ICurve;
18e41f4b71Sopenharmony_ci  ```
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci- [responsiveSpringMotion](../reference/apis/js-apis-curve.md#curvesresponsivespringmotion9): creates a responsive spring animation curve. It is a special case of **springMotion**, with the only difference in the default values. It is typically used to create an animation with a gesture on the screen. You can use **springMotion** to create an animation for when the user lifts their finger off the screen. The created animation automatically inherits the previous velocity for animation transition.
22e41f4b71Sopenharmony_ci  When the **overlapDuration** parameter of the new animation is not **0** and the previous spring animation of the current attribute is not yet complete, **response** and **dampingFracion** transit, over the period specified by **overlapDuration**, from the values of the previous animation to that of the new animation.
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci  ```ts
26e41f4b71Sopenharmony_ci  function responsiveSpringMotion(response?: number, dampingFraction?: number, overlapDuration?: number): ICurve;
27e41f4b71Sopenharmony_ci  ```
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci- [interpolatingSpring](../reference/apis/js-apis-curve.md#curvesinterpolatingspring10): creates an interpolating spring curve animated from 0 to 1. It applies to scenarios where the initial animation velocity needs to be specified. The animation duration is automatically calculated, and the manually specified animation duration does not take effect.
31e41f4b71Sopenharmony_ci  The actual animation value is calculated based on the curve. Therefore, the velocity should be the normalized speed, which is equal to the absolute speed of the animation attribute change divided by the amount of the animation attribute change. In light of this, this API is not applicable to the scenario where the attribute value of the animation start point is the same as that of the animation end point, since under this scenario, the amount of the animation attribute change is 0, and the normalized speed does not exist.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci  ```ts
35e41f4b71Sopenharmony_ci  function interpolatingSpring(velocity: number, mass: number, stiffness: number, damping: number): ICurve;
36e41f4b71Sopenharmony_ci  ```
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci- [springCurve](../reference/apis/js-apis-curve.md#curvesspringcurve9): creates a spring curve with the specified animation duration. This API is almost the same as **interpolatingSpring**. However, for an animation that uses **springCurve**, the physical duration of the curve is mapped to the specified duration, which is equivalent to stretching or compressing the curve on the time axis and violating the original physical rule of the curve. Whenever possible, avoid using this API.
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci  ```ts
42e41f4b71Sopenharmony_ci  function springCurve(velocity: number, mass: number, stiffness: number, damping: number): ICurve;
43e41f4b71Sopenharmony_ci  ```
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ciThe following shows a complete example and effect of spring curves. For details about how to connect gestures and animations, see [Animation Smoothing](arkts-animation-smoothing.md).
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci 
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci```ts
54e41f4b71Sopenharmony_ciimport curves from '@ohos.curves';
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ciclass Spring {
57e41f4b71Sopenharmony_ci  public title: string;
58e41f4b71Sopenharmony_ci  public subTitle: string;
59e41f4b71Sopenharmony_ci  public iCurve: ICurve;
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ci  constructor(title: string, subTitle: string, iCurve: ICurve) {
62e41f4b71Sopenharmony_ci    this.title = title;
63e41f4b71Sopenharmony_ci    this.iCurve = iCurve;
64e41f4b71Sopenharmony_ci    this.subTitle = subTitle;
65e41f4b71Sopenharmony_ci  }
66e41f4b71Sopenharmony_ci}
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci// Spring component
69e41f4b71Sopenharmony_ci@Component
70e41f4b71Sopenharmony_cistruct Motion {
71e41f4b71Sopenharmony_ci  @Prop dRotate: number = 0
72e41f4b71Sopenharmony_ci  private title: string = ""
73e41f4b71Sopenharmony_ci  private subTitle: string = ""
74e41f4b71Sopenharmony_ci  private iCurve: ICurve | undefined = undefined
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci  build() {
77e41f4b71Sopenharmony_ci    Column() {
78e41f4b71Sopenharmony_ci      Circle()
79e41f4b71Sopenharmony_ci        .translate({ y: this.dRotate })
80e41f4b71Sopenharmony_ci        .animation({ curve: this.iCurve, iterations: -1 })
81e41f4b71Sopenharmony_ci        .foregroundColor('#317AF7')
82e41f4b71Sopenharmony_ci        .width(30)
83e41f4b71Sopenharmony_ci        .height(30)
84e41f4b71Sopenharmony_ci
85e41f4b71Sopenharmony_ci      Column() {
86e41f4b71Sopenharmony_ci        Text(this.title)
87e41f4b71Sopenharmony_ci          .fontColor(Color.Black)
88e41f4b71Sopenharmony_ci          .fontSize(10).height(30)
89e41f4b71Sopenharmony_ci        Text(this.subTitle)
90e41f4b71Sopenharmony_ci          .fontColor(0xcccccc)
91e41f4b71Sopenharmony_ci          .fontSize(10).width(50)
92e41f4b71Sopenharmony_ci      }
93e41f4b71Sopenharmony_ci      .borderWidth({ top: 1 })
94e41f4b71Sopenharmony_ci      .borderColor(0xf5f5f5)
95e41f4b71Sopenharmony_ci      .width(80)
96e41f4b71Sopenharmony_ci      .alignItems(HorizontalAlign.Center)
97e41f4b71Sopenharmony_ci      .height(100)
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci    }
100e41f4b71Sopenharmony_ci    .height(110)
101e41f4b71Sopenharmony_ci    .margin({ bottom: 5 })
102e41f4b71Sopenharmony_ci    .alignItems(HorizontalAlign.Center)
103e41f4b71Sopenharmony_ci  }
104e41f4b71Sopenharmony_ci}
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci@Entry
107e41f4b71Sopenharmony_ci@Component
108e41f4b71Sopenharmony_ciexport struct SpringCurve {
109e41f4b71Sopenharmony_ci  @State dRotate: number = 0;
110e41f4b71Sopenharmony_ci  private springs: Spring[] = [
111e41f4b71Sopenharmony_ci    new Spring('springMotion', 'Cycle: 2, damping: 0.25', curves.springMotion(1, 0.25)),
112e41f4b71Sopenharmony_ci    new Spring('responsive' + '\n' + 'SpringMotion', 'Default responsive spring curve', curves.responsiveSpringMotion(1, 0.25)),
113e41f4b71Sopenharmony_ci    new Spring('interpolating' + '\n' + 'Initial velocity: 100; quality: 1; stiffness: 228; damping: 30', curves.interpolatingSpring(10, 1, 228, 30)),
114e41f4b71Sopenharmony_ci    new Spring('springCurve', 'Initial velocity: 100; quality: 1; stiffness: 228; damping: 30', curves.springCurve(10, 1, 228, 30))
115e41f4b71Sopenharmony_ci  ];
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci  build() {
118e41f4b71Sopenharmony_ci    Row() {
119e41f4b71Sopenharmony_ci      ForEach(this.springs, (item: Spring) => {
120e41f4b71Sopenharmony_ci        Motion({ title: item.title, subTitle: item.subTitle, iCurve: item.iCurve, dRotate: this.dRotate })
121e41f4b71Sopenharmony_ci      })
122e41f4b71Sopenharmony_ci    }
123e41f4b71Sopenharmony_ci    .justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Bottom)
124e41f4b71Sopenharmony_ci    .width('100%')
125e41f4b71Sopenharmony_ci    .height(437)
126e41f4b71Sopenharmony_ci    .margin({ top: 20 })
127e41f4b71Sopenharmony_ci    .onClick(() => {
128e41f4b71Sopenharmony_ci      this.dRotate = -50;
129e41f4b71Sopenharmony_ci    })
130e41f4b71Sopenharmony_ci  }
131e41f4b71Sopenharmony_ci}
132e41f4b71Sopenharmony_ci```
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci
136e41f4b71Sopenharmony_ci![en-us_image_0000001649089041](figures/en-us_image_0000001649089041.gif)
137