• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Spring Curve Animation
2
3
4ArkUI provides [Preset Animation Curve] (../reference/arkui-ts/ts-appendix-enums.md#curve), which specifies the change rule of animation attributes from the start value to the end value, such as Linear, Ease, and EaseIn. At the same time, ArkUI also provides spring curves generated by the physical model of spring oscillators. Through the spring curve, developers can set the end value to be exceeded and oscillate around the end value until the end value stops. The animation effect of spring curve is more interactive and playable than other curves.
5
6
7There are two types of interfaces for spring curves: [springCurve](../reference/apis/js-apis-curve.md#curvesspringcurve9) and [springMotion](../reference/apis/js-apis-curve.md#curvesspringmotion9) and [responsiveSpringMotion](../reference/apis/js-apis-curve.md#curvesresponsivespringmotion9). Spring curves can be generated in both modes.
8
9
10## Using springCurve
11
12The **springCurve** API is as follows:
13
14
15```ts
16springCurve(velocity: number, mass: number, stiffness: number, damping: number)
17```
18
19The structural parameters include the initial velocity, the mass, stiffness and damping of the spring system. When building springCurve, you can set the quality to 1. Adjust the stiffness and damping parameters based on the parameter description in springCurve to achieve the desired oscillation effect.
20
21
22
23```ts
24import curves from '@ohos.curves';
25@Entry
26@Component
27struct SpringTest {
28  @State translateX: number = 0;
29
30  private jumpWithSpeed(speed: number) {
31    this.translateX = -1;
32    animateTo({ duration: 2000, curve: curves.springCurve(speed, 1, 1, 1.2) }, () => {
33      //Spring animation for translation in the x direction at the specified initial speed
34      this.translateX = 0;
35    })
36  }
37
38  build() {
39    Column() {
40      Button("button")
41        .fontSize(14)
42        .width(100)
43        .height(50)
44        .margin(30)
45        .translate({ x: this.translateX })
46      Row({space:50}) {
47        Button("jump 50").fontSize(14)
48          .onClick(() => {
49            //Translate the spring curve with an initial speed of 50.
50            this.jumpWithSpeed(50);
51          })
52        Button("jump 200").fontSize(14)
53          .onClick(() => {
54            //Translate the spring curve with an initial speed of 200.
55            this.jumpWithSpeed(200);
56          })
57      }.margin(30)
58    }.height('100%').width('100%')
59  }
60}
61```
62
63
64![springCurve](figures/springCurve.gif)
65
66
67In the preceding example, when different buttons are clicked and different initial speeds of springCurve are given, the buttons reach the specified positions elastically, and the amplitude of the buttons increases with the speed. In addition, you can modify the mass, stiffness, and damping parameters of springCurve to achieve the desired elasticity.
68
69
70>**NOTE**
71>
72>The speed only amplifies the oscillation effect, but whether the system can produce the oscillation effect depends on the physical parameters of the spring oscillator, that is, mass, stiffness, and damping. The smaller the stiffness and the larger the damping, the weaker the "elasticity" of springCurve and the weaker the oscillation effect. With the decrease of stiffness or the increase of damping, no matter how large the velocity is, there will be no oscillation near the end value.
73
74
75## Using springMotion and responsiveSpringMotion
76
77The interfaces of the [springMotion](../reference/apis/js-apis-curve.md#curvesspringmotion9) are as follows:
78
79
80```ts
81springMotion(response?: number, dampingFraction?: number, overlapDuration?: number)
82```
83
84The interfaces of the [responsiveSpringMotion](../reference/apis/js-apis-curve.md#curvesresponsivespringmotion9) are as follows:
85
86
87```ts
88responsiveSpringMotion(response?: number, dampingFraction?: number, overlapDuration?: number)
89```
90
91Their construction parameters include three optional parameters: spring natural vibration period, damping coefficient, and elastic animation connection duration. For details about the parameters, see their documents.
92
93
94When the springMotion and responsiveSpringMotion curves are used, the duration parameter does not take effect. This parameter is applicable to hand animation.
95
96
97
98```ts
99import curves from '@ohos.curves';
100
101@Entry
102@Component
103struct SpringMotionTest {
104  @State positionX: number = 100;
105  @State positionY: number = 100;
106  diameter: number = 50;
107
108  build() {
109    Column() {
110      Row() {
111        Circle({ width: this.diameter, height: this.diameter })
112          .fill(Color.Blue)
113          .position({ x: this.positionX, y: this.positionY })
114          .onTouch((event: TouchEvent) => {
115            if (event.type === TouchType.Move) {
116              // Follow-up process. Use the responsiveSpringMotion curve.
117              animateTo({ curve: curves.responsiveSpringMotion() }, () => {
118                //subtract the radius so that the center of the ball moves to the finger position
119                this.positionX = event.touches[0].screenX - this.diameter / 2;
120                this.positionY = event.touches[0].screenY - this.diameter / 2;
121                console.info(`move, animateTo x:${this.positionX}, y:${this.positionY}`);
122              })
123            } else if (event.type === TouchType.Up) {
124              //Use the springMotion curve when you leave your hand.
125              animateTo({ curve: curves.springMotion() }, () => {
126                this.positionX = 100;
127                this.positionY = 100;
128                console.info(`touchUp, animateTo x:100, y:100`);
129              })
130            }
131          })
132      }
133      .width("100%").height("80%")
134      .clip(true) //If the ball exceeds the range of the parent component, the ball is invisible.
135      .backgroundColor(Color.Orange)
136
137      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) {
138        Text("Drag the ball").fontSize(16)
139      }
140      .width("100%")
141
142      Row() {
143        Text('Click position: [x:' + Math.round(this.positionX) +', y:' + Math.round(this.positionY) + ']').fontSize(16)
144      }
145      .padding(10)
146      .width("100%")
147    }.height('100%').width('100%')
148  }
149}
150```
151
152
153The preceding code is an example of hand animation. In the onTouch event, the touch position is captured and the translate or position attribute of the component is changed so that the component moves to the touch position when following the hand. After the hand is released, the component returns to the original position. The following figure shows the effect of the follower animation.
154
155
156![springMotion](figures/springMotion.gif)
157
158
159The responsiveSpringMotion curve is recommended for the follow-up process, and the springMotion curve is recommended for the release process. The follow-up process is triggered for multiple times as the position of the hand changes. Therefore, the responsiveSpringMotion animation is started for multiple times. When the hand is released, the springMotion animation is started once. During the follow-up and release processes, an animation is executed on the same attribute of the same object, and the springMotion or responsiveSpringMotion curve is used. Each time the animation is started, the speed used by the last animation is inherited, implementing smooth transition.
160
161
162>**NOTE**
163>
164>  1. SpringCurve can be used to set the initial speed. If a single attribute has multiple animations, the animations do not affect each other. The effects of multiple animations are superimposed.
165>
166>  2. Although springMotion has an internal speed mechanism, it cannot be set by developers. When multiple animations exist for a single attribute, the later animation replaces the previous animation and inherits the speed of the previous animation.
167