当前位置:首页 > 科技  > 软件

水波纹动画开发(ArkUI)

来源: 责编: 时间:2023-12-20 17:46:03 163观看
导读想了解更多关于开源的内容,请访问:51CTO 开源基础软件社区https://ost.51cto.com场景介绍在日常应用场景中,水波纹的效果比较常见,例如数字键盘按键效果、听歌识曲、附近搜索雷达动效等等,本文就以数字按键为例介绍水波纹

2d428资讯网——每日最新资讯28at.com

想了解更多关于开源的内容,请访问:2d428资讯网——每日最新资讯28at.com

51CTO 开源基础软件社区2d428资讯网——每日最新资讯28at.com

https://ost.51cto.com2d428资讯网——每日最新资讯28at.com

场景介绍

在日常应用场景中,水波纹的效果比较常见,例如数字键盘按键效果、听歌识曲、附近搜索雷达动效等等,本文就以数字按键为例介绍水波纹动效的实现。2d428资讯网——每日最新资讯28at.com

效果呈现

本例最终效果图如下:2d428资讯网——每日最新资讯28at.com

2d428资讯网——每日最新资讯28at.com

环境要求

本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:2d428资讯网——每日最新资讯28at.com

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

实现思路

本实例涉及到的主要特性及其实现方案如下:2d428资讯网——每日最新资讯28at.com

  • UI框架:使用Grid,GridItem等容器组件组建UI框架。
  • 按钮渲染:通过自定义numBtn组件(含Column、Button、Stack、Text等关键组件以及visibility属性),进行数字按钮的渲染。
  • 按钮状态变化:设置状态变量unPressed,控制按钮的当前状态,向Column组件添加onTouch事件,监听按钮的当前状态。
  • 默认状态为按钮放开状态(unPressed为true)。
  • 当按钮按下时,更新按钮的状态(unPressed:true -> false)。
  • 当按钮放开时,更新按钮的状态(unPressed:false -> true)。
  • 按钮动画展示:使用属性动画以及组件内转场动画绘制按钮不同状态下的动画。
  • 当按钮按下时,使用显式动画(animateTo)加载动画:插入按下时的Row组件,同时加载水波的聚拢效果。
  • 当按钮放开时,使用组件内转场加载动画:插入放开时的Row组件,同时加载水波的扩散效果。

开发步骤

针对实现思路中所提到的内容,具体关键开发步骤如下:2d428资讯网——每日最新资讯28at.com

先通过Grid,GridItem等容器组件将UI框架搭建起来,在GuidItem中引用步骤2中的自定义数字按钮numBtn构建出数字栅格。
具体代码如下:2d428资讯网——每日最新资讯28at.com

private numGrid: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, -1]   ...    Column() {      Grid() {        ForEach(this.numGrid, (item: number, index: number) => {          GridItem() {            ...          }        }, item => item)      }      .columnsTemplate('1fr 1fr 1fr')      .rowsTemplate('1fr 1fr 1fr 1fr')      .columnsGap(10)      .rowsGap(10)      .width(330)      .height(440)    }.width('100%').height('100%')

通过Column、Button、Stack、Text等关键组件以及visibility属性构建自定义数字按钮numBtn。
具体代码如下:2d428资讯网——每日最新资讯28at.com

@Componentstruct numBtn {  ···  build() {    Column() {        Button() {            stack(){                ...                Text(`${this.item}`).fontSize(30)            }            ...        }        .backgroundColor('#ccc')         .type(ButtonType.Circle)        .borderRadius(100)        .width(100)        .height(100)       }    .visibility(this.item == -1 ? Visibility.Hidden : Visibility.Visible)    .borderRadius(100)  }}

设置状态变量unPressed,监听当前数字按钮的状态,同时向Column组件添加onTouch事件,获取并更新按钮的当前状态,从而可以根据监听到的按钮状态加载对应的动画效果。
具体代码块如下:2d428资讯网——每日最新资讯28at.com

//状态变量unPressed,用于监听按钮按下和放开的状态@State unPressed: boolean = true ...// 添加onTouch事件,监听状态.onTouch((event: TouchEvent) => {  // 当按钮按下时,更新按钮的状态(unPressed:true -> false)  if (event.type == TouchType.Down) {    animateTo({ duration: 400 }, () => {      this.unPressed = !this.unPressed      this.currIndex = this.index    })  }  // 当按钮放开时,更新按钮的状态(unPressed:false -> true)  if (event.type == TouchType.Up) {    animateTo({ duration: 400 }, () => {      this.unPressed = !this.unPressed    })  }})

根据按钮组件的按下/放开状态,通过if-else语句选择插入的Row组件,并随之呈现不同的水波动画效果(按下时水波聚拢,放开时水波扩散)。
具体代码块如下:2d428资讯网——每日最新资讯28at.com

Stack() {  Row() {    // 判断当前按钮组件为放开状态    if (this.unPressed && this.currIndex == this.index) {      // 插入Row组件,配置过渡效果      Row()        .customStyle()        .backgroundColor('#fff')          // 水波纹扩散动画:从Row组件的中心点开始放大,scale{0,0}变更scale{1,1}(完整显示)        .transition({          type: TransitionType.Insert,          opacity: 0,          scale: { x: 0, y: 0, centerY: '50%', centerX: '50%' }        })    }    // 判断当前按钮组件为按下状态    else if (!this.unPressed && this.currIndex == this.index) {      // 插入Row组件,配置过渡效果      Row()        .customStyle()        .backgroundColor(this.btnColor)        .scale(this.btnScale)        .onAppear(() => {          // 水波纹聚拢动画:Row组件backgroundColor属性变更(#ccc -> #fff),插入动画过渡效果,scale{1,1}(完整显示)变化为scale{0,0}           animateTo({ duration: 300,            // 聚拢动画播放完成后,需要衔接扩散动画,Row组件backgroundColor属性变更(#fff -> #ccc),插入动画过渡效果,scale{0,0}变化为scale{1,1}(完整显示)            onFinish: () => {              this.btnColor = '#ccc'              this.btnScale = { x: 1, y: 1 }            } },            () => {              this.btnColor = '#fff'              this.btnScale = { x: 0, y: 0 }            })        })    }    // 其他状态    else {      Row()        .customStyle()        .backgroundColor('#fff')    }  }  .justifyContent(FlexAlign.Center)  .alignItems(VerticalAlign.Center)  .borderRadius(100)  Text(`${this.item}`).fontSize(30)}.customStyle()

完整代码

示例代码如下:2d428资讯网——每日最新资讯28at.com

@Entry@Componentexport default struct dragFire {  private numGrid: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, -1]  build() {    Column() {      Grid() {        ForEach(this.numGrid, (item: number, index: number) => {          GridItem() {            numBtn({ item: item, index: index })          }        }, item => item)      }      .columnsTemplate('1fr 1fr 1fr')      .rowsTemplate('1fr 1fr 1fr 1fr')      .columnsGap(10)      .rowsGap(10)      .width(330)      .height(440)    }.width('100%').height('100%')  }}@Componentstruct numBtn {  private currIndex: number = -1  //状态变量unPressed,用于控制按钮的状态  @State unPressed: boolean = true  @State btnColor: string = '#ccc'  index: number  item: number  @State btnScale: {    x: number,    y: number  } = { x: 1, y: 1 }  @Styles customStyle(){    .width('100%')    .height('100%')    .borderRadius(100)  }  build() {    Column() {      Button() {        Stack() {          Row() {            // 判断当前组件为放开状态            if (this.unPressed && this.currIndex == this.index) {              // 插入Row组件,配置过渡效果              Row()                .customStyle()                .backgroundColor('#fff')                  // 水波纹扩散动画:Row组件backgroundColor属性变更(#fff -> #ccc),系统插入动画过渡效果,从组建的中心点开始放大,scale{0,0}变更scale{1,1}                .transition({                  type: TransitionType.Insert,                  opacity: 0,                  scale: { x: 0, y: 0, centerY: '50%', centerX: '50%' }                })            }            // 判断当前组件为按下状态            else if (!this.unPressed && this.currIndex == this.index) {              // 插入Row组件,配置过渡效果              Row()                .customStyle()                .backgroundColor(this.btnColor)                .scale(this.btnScale)                .onAppear(() => {                  // 水波纹聚拢动画:Row组件backgroundColor属性变更(#ccc -> #fff),插入动画过渡效果,scale{1,1}变化为scale{0,0}                  animateTo({ duration: 300,                    // 聚拢动画播放完成后,需要衔接扩散动画,此时Row组件backgroundColor属性变更(#fff -> #ccc),插入动画过渡效果,scale{0,0}变化为scale{1,1}                    onFinish: () => {                      this.btnColor = '#ccc'                      this.btnScale = { x: 1, y: 1 }                    } },                    () => {                      this.btnColor = '#fff'                      this.btnScale = { x: 0, y: 0 }                    })                })            }            // 其他状态            else {              Row()                .customStyle()                .backgroundColor('#fff')            }          }          .justifyContent(FlexAlign.Center)          .alignItems(VerticalAlign.Center)          .borderRadius(100)          Text(`${this.item}`).fontSize(30)        }        .customStyle()      }      .stateEffect(false)      .backgroundColor('#ccc')      .type(ButtonType.Circle)      .borderRadius(100)      .width(100)      .height(100)    }    .visibility(this.item == -1 ? Visibility.Hidden : Visibility.Visible)    .borderRadius(100)    // onTouch事件,监听状态    .onTouch((event: TouchEvent) => {      // 当按钮按下时,更新按钮的状态(unPressed:true -> false)      if (event.type == TouchType.Down) {        animateTo({ duration: 400 }, () => {          this.unPressed = !this.unPressed          this.currIndex = this.index        })      }      // 当按钮放开时,更新按钮的状态(unPressed:false -> true)      if (event.type == TouchType.Up) {        animateTo({ duration: 400 }, () => {          this.unPressed = !this.unPressed        })      }    })  }}

想了解更多关于开源的内容,请访问:2d428资讯网——每日最新资讯28at.com

51CTO 开源基础软件社区2d428资讯网——每日最新资讯28at.com

https://ost.51cto.com2d428资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-50743-0.html水波纹动画开发(ArkUI)

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 如何调用设备摄像头进行拍照、预览并将拍摄结果保存在媒体库中(Camera)

下一篇: 微服务集成中的三个常见缺陷,以及如何避免它们

标签:
  • 热门焦点
Top