how-to-develop-spring-animation.md 9.6 KB
Newer Older
D
duangavin123 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
# 如何使用弹簧动画曲线

## 场景说明
在动画开发场景中,经常用到弹性效果,尤其在拖拽某个对象时经常伴随弹性动效。OpenHarmony提供了三种弹簧动画曲线用来实现弹性效果,本例将为大家介绍这三种曲线的用法。

## 效果呈现
本例最终效果如下:

![springanimation](figures/springanimation.gif)

## 运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:

- IDE: DevEco Studio 3.1 Beta2
- SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)


## 实现思路
本例主要用到以下三种弹簧动画曲线:
- [curves.springCurve](../application-dev/reference/apis/js-apis-curve.md#curvesspringcurve9):通过设置弹簧的初始速度、质量、刚度和阻尼来控制弹簧动画的效果。对应本例中springCurve按钮触发的动画。
- [curves.springMotion](../application-dev/reference/apis/js-apis-curve.md#curvesspringmotion9):通过设置弹簧震动时间和阻尼来控制弹簧动画的效果。对应本例中springMotion按钮触发的动画。
- [curves.responsiveSpringMotion](../application-dev/reference/apis/js-apis-curve.md#curvesresponsivespringmotion9):构造弹性跟手动画曲线对象,是springMotion的一种特例,仅默认参数不同,可与springMotion混合使用。用来实现拖拽动画。

## 开发步骤
1. 搭建UI框架。
样例中有两个按钮,一个图片。内容整体纵向分布,两个按钮横向分布。纵向布局可以采用Column组件,横向布局可以采用Row组件。代码如下:
    ```ts
    @Entry
    @Component
    struct ImageComponent {
      build() {
        Column() {
          Row() {
            Button('springCurve')
              .margin({right:10})
              .fontSize(20)
              .backgroundColor('#18183C')
            Button('springMotion')
              .fontSize(20)
              .backgroundColor('#18183C')
          }
          .margin({top:30})

          Image($r("app.media.contact2"))
            .width(100)
            .height(100)
        }.width("100%").height("100%").backgroundColor('#A4AE77')
      }
    }
    ```
2. 为springCurve按钮添加curves.springCurve的曲线动画。
    ```ts
    ...
    // 定义状态变量translateY,用来控制笑脸图像的位移
    @State translateY: number = 0
    	...
        Button('springCurve')
          .margin({right:10})
          .fontSize(20)
          .backgroundColor('#18183C')
          // 绑定点击事件
          .onClick(() => {
            // 在点击事件中添加显示动画
            animateTo({
              duration: 2000,
              // 设定curves.springCurve为动画曲线
              curve: curves.springCurve(100, 10, 80, 10)
            },
            () => {
              // 改变translateY的值,使笑脸图像发生位移
              this.translateY = -20
            })
            this.translateY = 0
          })
    	...
        Image($r("app.media.contact2"))
          .width(100)
          .height(100)
          // 为笑脸图像添加位移属性,以translateY为参数
          .translate({ y: this.translateY })
    	...
    ```
    效果如下:
    
    ![springCurve](figures/springCurve.gif)
3. 为springMotion按钮添加curves.springMotion曲线动画。
这里通过position属性控制springMotion按钮的移动,当然开发者也可以继续选择使用translate属性。
    ```ts
    ...
      // 定义状态变量translateY,用来控制笑脸图像的位置变化
      @State imgPos: {
        x: number,
        y: number
      } = { x: 125, y: 400 }
            ...
            Button('springMotion')
              .fontSize(20)
              .backgroundColor('#18183C')
              // 绑定点击事件
              .onClick(() => {
              // 在点击事件中添加显示动画
              animateTo({
                duration: 15,
                //设定curves.springMotion为动画曲线
                curve: curves.springMotion(0.5, 0.5),
                onFinish: () => {
                  animateTo({ duration: 500,
                    curve: curves.springMotion(0.5, 0.5), }, () => {
                    // 动画结束时笑脸图像位置还原
                    this.imgPos = { x: 125, y: 400 }
                  })
                }
              }, () => {
                // 改变笑脸图像位置,y轴位置由400,变为150
                this.imgPos = { x: 125, y: 150 }
              })
            })
          ...
          Image($r("app.media.contact2"))
            .width(100)
            .height(100)
            .translate({ y: this.translateY })
            // 为笑脸图像添加位置属性,以imgPos为参数
            .position(this.imgPos)
         ...
    ```
    效果如下:
  
    ![springmotion](figures/springmotion.gif)
4. 使用curves.responsiveSpringMotion为笑脸图像添加拖拽动画。
    ```ts
    ...
          Image($r("app.media.contact2"))
            .width(100)
            .height(100)
            .translate({ y: this.translateY })
            .position(this.imgPos)
            // 绑定触摸事件
            .onTouch((event: TouchEvent) => {
              // 当触摸放开时,笑脸图像位置还原
              if (event.type == TouchType.Up) {
                animateTo({
                  duration: 50,
                  delay: 0,
                  curve: curves.springMotion(),
                  onFinish: () => {
                  }
                }, () => {
                  this.imgPos = { x: 125, y: 400 }
                })
              } else {
                // 触摸过程中触发跟手动画
                animateTo({
                  duration: 50,
                  delay: 0,
                  //设定跟手动画曲线
                  curve: curves.responsiveSpringMotion(),
                  onFinish: () => {
                  }
                }, () => {
                  // 根据触点位置改变笑脸图像位置,从而实现跟手动画
                  this.imgPos = {
                    x: event.touches[0].screenX - 100 / 2,
                    y: event.touches[0].screenY - 100 / 2
                  }
                })
              }
            })
    ...
    ```
    效果如下:
    
    ![responsivemotion](figures/responsivemotion.gif)

## 完整代码
本例完整代码如下:
```ts
import curves from '@ohos.curves';

@Entry
@Component
struct ImageComponent {
  // 定义状态变量translateY,用来控制笑脸图像的位移
  @State translateY: number = 0
  // 定义状态变量translateY,用来控制笑脸图像的位置变化
  @State imgPos: {
    x: number,
    y: number
  } = { x: 125, y: 400 }

  build() {
    Column() {
      Row() {
        Button('springCurve')
          .margin({right:10})
          .fontSize(20)
          .backgroundColor('#18183C')
          // 绑定点击事件
          .onClick(() => {
            // 在点击事件中添加显示动画
            animateTo({
              duration: 2000,
              // 设定curves.springCurve为动画曲线
              curve: curves.springCurve(100, 10, 80, 10)
            },
            () => {
              // 改变translateY的值,使笑脸图像发生位移
              this.translateY = -20
            })
            this.translateY = 0
          })
        Button('springMotion')
          .fontSize(20)
          .backgroundColor('#18183C')
          // 绑定点击事件
          .onClick(() => {
            // 在点击事件中添加显示动画
            animateTo({
              duration: 15,
              //设定curves.springMotion为动画曲线
              curve: curves.springMotion(0.5, 0.5),
              onFinish: () => {
                animateTo({ duration: 500,
                  curve: curves.springMotion(0.5, 0.5), }, () => {
                  // 动画结束时笑脸图像位置还原
                  this.imgPos = { x: 125, y: 400 }
                })
              }
            }, () => {
              // 改变笑脸图像位置,y轴位置由400,变为150
              this.imgPos = { x: 125, y: 150 }
            })
        })
      }
      .margin({top:30})

      Image($r("app.media.contact2"))
        .width(100)
        .height(100)
        // 为笑脸图像添加位移属性,以translateY为参数
        .translate({ y: this.translateY })
        // 为笑脸图像添加位置属性,以imgPos为参数
        .position(this.imgPos)
        // 绑定触摸事件
        .onTouch((event: TouchEvent) => {
          // 当触摸放开时,笑脸图像位置还原
          if (event.type == TouchType.Up) {
            animateTo({
              duration: 50,
              delay: 0,
              curve: curves.springMotion(),
              onFinish: () => {
              }
            }, () => {
              this.imgPos = { x: 125, y: 400 }
            })
          } else {
            // 触摸过程中触发跟手动画,同样通过animateTo实现动画效果
            animateTo({
              duration: 50,
              delay: 0,
              //设定跟手动画曲线
              curve: curves.responsiveSpringMotion(),
              onFinish: () => {
              }
            }, () => {
              // 根据触点位置改变笑脸图像位置,从而实现跟手动画
              this.imgPos = {
                x: event.touches[0].screenX - 100 / 2,
                y: event.touches[0].screenY - 100 / 2
              }
            })
          }
        })
    }.width("100%").height("100%").backgroundColor('#A4AE77')
  }
}
```
## 参考
- [显示动画](../application-dev/reference/arkui-ts/ts-explicit-animation.md)
- [插值计算](../application-dev/reference/apis/js-apis-curve.md)