HarmonyNext动画大全02-显式动画

简介: HarmonyNext动画大全02-显式动画

HarmonyNext动画大全02-显式动画

前言

上一篇文章我们介绍过属性动画animation的使用方法,那么本文就来学习和了解一下显示动画animateTo

animateTo

我们称之为显式动画,它本身是一个全局函数,通过调用函数的形式实现动画效果。显式动画animateTo和之前的属性动画

animation最大的区别在于 显式动画可以利用本身函数的特性实现多个显式动画连续调用,从而实现连贯性的动画。

基本语法

animateTo(value: AnimateParam, event: () => void): void

参数 类型 是否必填 描述
value AnimateParam 设置动画效果相关参数。
event () => void 指定动效的闭包函数

解释:

  1. AnimateParam 动画属性,在上一篇文章**《HarmonyNext动画大全01-属性动画》**内有详细介绍过
名称 描述 示例
duration 动画执行时间,单位毫秒 1000
tempo 动画执行速度,默认是1,最小是0 1
curve 动画曲线 比如匀速、先快后慢等 Curve.linear
delay 延迟时间 单位毫秒 1000
iterations 动画执行次数,-1 为无限 1
playMode 动画播放模式 如播放两次时,每次都是从头开始播放 PlayMode.Normal
onFinish 动画结束的回调函数
  1. 其中,onFinish 是我们实现连续动画的关键
  2. event 指定动效的闭包函数

基本示例

dd5e51d9f663ff92099111c70c74188d.png

@Entry
@Component
struct Index {
  @State
  scaleXY: number = 1
  build() {
    Column() {
      Button("点我就变大啦")
        .scale({ x: this.scaleXY, y: this.scaleXY })
        .onClick(() => {
          //   显式动画
          animateTo({
            // 1 指定动画参数
            duration: 1000
          }, () => {
            // 2 指定动效的闭包函数
            this.scaleXY = 2
          })
        })
    }
    .width("100%")
    .height("100%")
    .padding(40)
  }
}

代码解释

  1. 可以看到 animateTo就是一个全局函数,可以直接调用
  2. duration: 1000 表示动画参数,动画的持续时间为1s
  3. this.scaleXY = 2 放在 animateTo的第二个参数上,回调函数,也是在这里指定要具体执行的动画效果

至此,我们发现 显式动画 animateTo 和 之前的属性动画 animation 没有太大区别。 对的,因为他们两个最大的区别就在于 animateTo 可以比较方便实现连续多个动画效果

连续多个动画效果

如下图:

6d9c4183b5b28037299cd43cb09c5592.png

可以看到以上动画其实是有多个动画效果组合在一起的。如

  1. 左上角 -> 右上角
  2. 右上角 -> 右下角
  3. 右下角 -> 左下角
  4. 左下角 -> 左上角

我们思考:该如何实现呢?

答案是:onFinishonFinish 是动画参数中的一个属性,表示动画执行完毕。

onFinish

当动画执行完毕时,便会自动触发 onFinish里面的逻辑

ecc4801739cfe848d288fe50ab5232b0.png

@Entry
@Component
struct Index {
  @State
  x: number = 0
  @State
  y: number = 0
  build() {
    Column() {
      Row()
        .width(100)
        .height(100)
        .backgroundColor("#499C54")// tips: translate 表示设置位移
        .translate({
          x: this.x,
          y: this.y
        })
        .onClick(() => {
          animateTo({
            // 动画执行完毕触发
            onFinish: () => {
              AlertDialog.show({ message: "动画执行完毕" })
            }
          }, () => {
            this.x = 100
            this.y = 0
          })
        })
    }
    .width("100%")
    .height("100%")
    .alignItems(HorizontalAlign.Start)
  }
}

因此,当我们想要实现连续执行多个动画时,就不断往onFinish里面套娃即可

6d9c4183b5b28037299cd43cb09c5592.png

@Entry
@Component
struct Index {
  @State
  x: number = 0
  @State
  y: number = 0
  build() {
    Column() {
      Row()
        .width(100)
        .height(100)
        .backgroundColor("#499C54")
        .translate({
          x: this.x,
          y: this.y
        })
        .onClick(() => {
          // 1 左上角 -> 右上角
          animateTo({
            onFinish: () => {
              // 2 右上角 -> 右下角
              animateTo({
                onFinish: () => {
                  // 3 右下角 -> 左下角
                  animateTo({
                    onFinish: () => {
                      // 4 左下角 -> 左上角
                      animateTo({}, () => {
                        this.x = 0
                        this.y = 0
                      })
                    }
                  }, () => {
                    this.x = 0
                    this.y = 100
                  })
                }
              }, () => {
                this.x = 100
                this.y = 100
              })
            }
          }, () => {
            this.x = 100
            this.y = 0
          })
        })
    }
    .width("100%")
    .height("100%")
    .alignItems(HorizontalAlign.Start)
  }
}

以上这个代码,就可以实现连续动画了。

回调函数地狱


但是,这个代码结构,妈妈看到了很难不夸你写得好

以上结构已经形成了一个回调函数地狱了,小伙伴们~😂

解决回调函数地狱

有开发经验的小伙们应该可以马上想到解决方法

  1. promise
  2. asyncawait

对的,回调函数地狱可以靠这两个老哥来解决。

先拿 animateToPromise 做一个封装

const animateToPromise = (option: AnimateParam, fn: Function) => {
  const promise: Promise<undefined> = new Promise((resolve: Function) => {
    option.onFinish = () => {
      resolve()
    }
    animateTo(option, () => {
      fn()
    })
  })
  return promise
}

最后再来看解决后的版本

Row() {
  }
  .width(100)
  .height(100)
  .backgroundColor("#499C54")
  .translate({ x: this.x, y: this.y })
  .onClick(async () => {
    // 1 左上角 -> 右上角
    await animateToPromise({}, () => {
      this.x = 100
      this.y = 0
    })
    // 2 右上角 -> 右下角
    await animateToPromise({}, () => {
      this.x = 100
      this.y = 100
    })
    // 3 右下角 -> 左下角
    await animateToPromise({}, () => {
      this.x = 0
      this.y = 100
    })
    // 4 左下角 -> 左上角
    await animateToPromise({}, () => {
      this.x = 0
      this.y = 0
    })
  })


可以看到,封装后的代码,要简洁不少

小结

  1. animateTo 适合用在连续多个动画效果上
  2. animateTo 可以搭配promiseasyncawait 解决回调地狱的问题
  3. 由于篇幅问题,这里没有直接介绍promise和async。
目录
相关文章
|
移动开发 前端开发 JavaScript
【前端动画】实现动画的6种方式
【前端动画】实现动画的6种方式
1192 0
|
存储 文件存储 云计算
不瞒了,我们和追光动画有一个《杨戬》!
不瞒了,我们和追光动画有一个《杨戬》!
189 0
|
存储 缓存 Android开发
RecyclerView 动画原理 | 如何存储并应用动画属性值?
RecyclerView 动画原理 | 如何存储并应用动画属性值?
85 0
|
XML 图形学 数据格式
Animation组合动画踩坑-实现循环播放动画,可控制次数
Animation组合动画踩坑-实现循环播放动画,可控制次数
|
JavaScript 开发者
动画-使用过渡名实现动画|学习笔记
快速学习动画-使用过渡名实现动画
动画-使用过渡名实现动画|学习笔记
|
前端开发
动画
动画
139 0
|
Dart 开发者
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
180 0
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(三)
|
前端开发 图形学 Python
动画系统之2D动画
动画系统之2D动画
181 0
动画系统之2D动画
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(二)
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(二)
177 0
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(一)
【Flutter】Animation 动画 ( AnimatedBuilder 动画使用流程 | 创建动画控制器 | 创建动画 | 创建动画作用的组件 | 关联动画与组件 | 动画执行 )(一)
157 0