当前位置: 首页 > article >正文

HarmonyOS Next系列之水波纹动画特效实现(十三)

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉浸式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)
HarmonyOS Next系列之地图组件(Map Kit)使用(九)
HarmonyOS Next系列之半圆环进度条实现(十)
HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)
HarmonyOS Next系列之水波纹动画特效实现(十三)


文章目录

  • 系列文章目录
  • 前言
  • 一、实现原理
  • 二、显式动画 (animateTo)使用回顾
    • 入参
  • 三、代码实现
    • 示例一:
    • 示例二:


前言

HarmonyOS Next(基于API12)实现水波纹动画特效。

请添加图片描述


一、实现原理

画3个等比例放大的圆形,通过显示动画animateTo动态改变圆形放大系数和透明度

二、显式动画 (animateTo)使用回顾

animateTo显式动画接口来指定由于闭包代码导致的状态变化插入过渡动效。同属性动画,布局类改变宽高的动画,内容都是直接到终点状态

入参

animateTo(value: AnimateParam, event: () => void): void
在这里插入图片描述
说明:
value 设置动画参数例如动画时长、动画速度、动画延迟等。
event:回调函数,指定组件最终状态,动画将从初始态到最终态自动插入过度动画


AnimateParam常用属性:

名称类型说明
durationnumber动画持续时长,单位ms
curveCurve Curve9+ string动画曲线默认值Curve.EaseInOut
delaynumber动画延迟执行时间单位ms
iterationsnumber动画播放次数,默认播放一次,设置为-1时表示无限次播放。设置为0时表示无动画效果
playModePlayMode动画播放模式,默认播放完成后重头开始播放

显示动画需要有个触发点去调用animateTo(),绑定在哪个组件上就需要在当前组件的事件下调用animateTo()动画才能生效。
常见使用场景放置点击事件,不符合我们当前要实现的。实现水波纹动画需要组件渲染完自动触发动画,所以我们可以考虑放在组件的onAppear事件上,onAppear为组件挂载显示后触发此回调。

更多显式动画 (animateTo)使用请看官方文档

三、代码实现

示例一:

图标水波纹动画特效:

@Entry
@Component
struct Demo {
  @State scaleList: number[] = [] //缩放比例数据
  @State opacityList: number[] = [] //透明度数据
  private cloneScaleList: number[] = [] //备份初始缩放比例数据
  private cloneOpacityList: number[] = [] //备份初始透明度数据
  private scaleRatio:number=0.7 //缩放增大比例

  aboutToAppear(): void {
    //初始化缩放比例和透明度,新建数组保存3个圆形对应数据 
    //缩放比例:[1,1.7,2.4]  透明度:[0.3,0.2,0.1]
    this.scaleList = new Array(3).fill('').map((item: string, index: number) => 1 + index * this.scaleRatio)
    this.opacityList = new Array(3).fill('').map((item: string, index: number) => (3 - index)/10 )
    this.cloneScaleList = this.scaleList.slice()
    this.cloneOpacityList = this.opacityList.slice()
  }

  build() {
    Column({ space: 50 }) {
      Stack() {
        ForEach(this.scaleList, (item: number, index: number) => {
          Column() {
          }
          .width(50)
          .height(50)
          .borderRadius(25)
          .backgroundColor('#1463F4')
          .opacity(this.opacityList[index])
          .scale({ x: this.scaleList[index], y: this.scaleList[index] })
          .onAppear(() => {
            animateTo({ duration: 1200, iterations: -1 }, () => {
            //每个圆缩放系数+0.7
              this.scaleList[index] = this.cloneScaleList[index] + this.scaleRatio
              //每个圆透明度-0.1
              this.opacityList[index] = this.cloneOpacityList[index] -  0.1
            })
          })
        }, (item: number, index: number) => index.toString())

        Image($r('app.media.app_icon')).width(50).borderRadius(25)
      }
    }.height('100%').width('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
  }
}

运行效果:
请添加图片描述

说明:初始化新建了3个圆形,通过变量scaleList保存了3个圆初始缩放比例为 [1,1.7,2.4],通过变量opacityList保存了初始透明度为[0.3,0.2,0.1],在每个圆的渲染完成回调函数onAppear中调用显示动画把每个圆增大0.7倍,变成[1.7,2.4,3.1],同时透明度减0.1,变成[0.2,0.1,0],动画属性设置iterations: -1循环播放,就形成了水波纹动画效果。

示例二:

按钮水波纹特效:

@Entry
@Component
struct Demo {
  @State scaleList: number[] = [] //缩放比例数据
  @State opacityList: number[] = [] //透明度数据
  private cloneScaleList: number[] = [] //备份初始缩放比例数据
  private cloneOpacityList: number[] = [] //备份初始透明度数据
  private scaleRatio: number = 0.3 //缩放增大比例

  aboutToAppear(): void {
    //初始化缩放比例和透明度
    this.scaleList = new Array(2).fill('').map((item: string, index: number) => 1 + index * this.scaleRatio)
    this.opacityList = new Array(2).fill('').map((item: string, index: number) => 0.3-index*0.15)
    this.cloneScaleList = this.scaleList.slice()
    this.cloneOpacityList = this.opacityList.slice()
  }

  build() {
    Column({ space: 50 }) {
      Stack() {
        ForEach(this.scaleList, (item: number, index: number) => {
          Column() {
          }
          .width(120)
          .height(50)
          .borderRadius(25)
          .backgroundColor('#007DFE')
          .opacity(this.opacityList[index])
          .scale({ x: this.scaleList[index], y: this.scaleList[index] })
          .onAppear(() => {
            animateTo({ duration: 1000, iterations: -1 }, () => {
              this.scaleList[index] = this.cloneScaleList[index] + this.scaleRatio
              this.opacityList[index] = this.cloneOpacityList[index] - 0.15
            })
          })
        }, (item: number, index: number) => index.toString())

        Button('提交', { type: ButtonType.Capsule }).width(120).height(50).borderRadius(25)
      }
    }.height('100%').width('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
  }
}

运行效果:
请添加图片描述


http://www.kler.cn/a/327067.html

相关文章:

  • Android App 技能在DuerOS的调试方法
  • 【初阶数据结构与算法】复杂度分析练习之轮转数组(多种方法)
  • qt QMenuBar详解
  • sparkSQL面试题
  • 4种鼓励创业创新的方法
  • 【AI】【提高认知】深度学习与反向传播:理解AI的基础
  • ClickHouse入库时间与实际相差8小时问题
  • 升级FreeBSD13.2到14.1-RELEASE
  • 树和二叉树知识点大全及相关题目练习【数据结构】
  • golang 获取证书的生效及过期时间
  • 【论文笔记】Flamingo: a Visual Language Model for Few-Shot Learning
  • Redis篇(应用案例 - 附近商户)(持续更新迭代)
  • Pgsql 数据库操作
  • 【运动控制】关于GPIO通用输入口是NPN型数字输入
  • Grafana指标汉化
  • 【测试-BUG篇】软件测试的BUG知识你了解多少呢?
  • 自动驾驶系列—DOW(开门预警):让每一次开门都更安心
  • 水囊在消防灭火工作中的作用
  • 机器人的性能指标
  • C++ | Leetcode C++题解之第448题找到所有数组中消失的数字
  • 使用 pypdf 给 PDF 添加目录书签
  • 如何避免IP污染
  • POST与GET有哪些区别?
  • Xcode手动安装SDK模拟器
  • 【Golang】Go语言中如何面向对象?
  • 【Git】Git在Unity中使用时的问题记录