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。
目录
相关文章
|
存储
uni-app将0000-00-00格式的时间转换为时间戳
uni-app将0000-00-00格式的时间转换为时间戳
294 1
|
移动开发 测试技术 开发工具
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
2280 1
【钉钉免登录】(详解)钉钉接口,H5微应用,钉钉免登录及获取当前用户信息
|
SQL 前端开发 Java
Java+Mysql图书管理系统(完整实训代码)
​ ✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(html css js) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页
990 0
|
API 容器 Kubernetes
当 K8s 集群达到万级规模,阿里巴巴如何解决系统各组件性能问题?
作者 | 阿里云容器平台高级技术专家 曾凡松(逐灵) 本文主要介绍阿里巴巴在大规模生产环境中落地 Kubernetes 的过程中,在集群规模上遇到的典型问题以及对应的解决方案,内容包含对 etcd、kube-apiserver、kube-controller 的若干性能及稳定性增强,这些关键的增强是阿里巴巴内部上万节点的 Kubernetes 集群能够平稳支撑 2019 年天猫 618 大促的关键所在。
|
8月前
鸿蒙开发:如何实现文本跑马灯效果
如果只是一个普通的跑马灯效果,而且Text文本组件中的TextOverflow.MARQUEE可以满足需求,以Text为主,如果你想控制文本的速度,暂停等功能,可以使用Marquee,如果你想实现复杂的场景滚动,比如图片,各种组件嵌套滚动,这种只能自己定义了。
223 1
鸿蒙开发:如何实现文本跑马灯效果
|
存储 Go
Go to Learn Go之类型转换
Go to Learn Go之类型转换
141 8
|
8月前
|
人工智能 前端开发 容器
鸿蒙开发:了解Canvas绘制
本文主要简单的概述了Canvas绘制的基础知识,大家作为一个简单的了解即可,下面的几篇文章,我们会对相关的绘制再做进一步的分析,首先可以先做一个简单的总结:DrawingRenderingContext在使用上远远没有CanvasRenderingContext2D使用起来方便,比如在修改画笔的粗细,颜色等属性上,就可以体现出来。
180 6
鸿蒙开发:了解Canvas绘制
|
缓存 负载均衡 监控
如何优化网络传输效率?
如何优化网络传输效率?
1395 2
|
XML API 网络架构
API协议 的十种技术特点及适用场景
本文介绍了十种常见的API协议技术,包括REST、GraphQL、gRPC、SOAP、WebSocket、AMF和XML-RPC等,每种技术都有其特点和适用场景,如REST适用于轻量级Web服务开发,gRPC适合高性能分布式系统,而WebSocket则适用于需要低延迟交互的应用。
|
关系型数据库 MySQL 中间件
【MySQL实战笔记】07 | 行锁功过:怎么减少行锁对性能的影响?-02 死锁和死锁检测
【4月更文挑战第19天】在高并发环境下,死锁发生在多个线程间循环等待资源时,导致无限期等待。MySQL中,死锁可通过`innodb_lock_wait_timeout`参数设置超时或`innodb_deadlock_detect`开启死锁检测来解决。默认的50s超时可能不适用于在线服务,而频繁检测会消耗大量CPU。应对热点行更新引发的性能问题,可以暂时关闭死锁检测(风险是产生大量超时),控制并发度,或通过分散记录减少锁冲突,例如将数据分拆到多行以降低死锁概率。
386 1