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 137