HarmonyOS 动画一:如何优雅编排控件

HarmonyOS 动画一:如何优雅编排控件

本文概述:

  • 技术背景:优化用户体验是移动端开发中老生常谈的话题,合理的动画植入可提升控件编排上的美感。
  • 文章大纲:基本动画:属性动画、显示动画、显示动画进阶之路径动画
  • 本文代码链接
  • 动画完整代码链接

属性动画

属性动画概述

  • 属性动画最大的特点:其在使用时,使用链式调用,作为被修饰对象的一个属性

  • 属性动画是什么

    • 在修饰对象的内置属性改变时,使用动画进行过渡。
    • 理论上讲,只要修饰对象的属性存在二值性,即可使用属性动画进行过渡
  • 属性动画有什么作用

    • 常用动画参数:用户可以指定什么

      • 参数:动画持续时间、动画播放速度、动画速率曲线、动画延迟执行时长、动画播放次数、动画播放模式、
      • 回调:在动画播放时触发
  • 我们怎么使用属性动画

    • 确定修饰对象的属性,及属性始末状态
    • 确定修饰作用域,及动画参数
  • 细节问题

    • 尽量不要对颜色使用属性动画过渡,因为实现的效果不固定
    • 在对尺寸进行变化时,需考虑变化前后及过程中对其余布局的影响

属性动画的使用步骤

  • 实际效果:可以用作进度条填充,做一个完整进度的实时动态展示

  • 首先,确定动画的作用对象及相关属性

    • 常用属性:宽高尺寸、摆放状态、控件样式
    • 一般使用@State 修饰控件状态变量,因为其值改变,会自动触发build() 二次执行
    less 复制代码
    @Entry
    @Component
    struct AttrAnimationPage {
      @State wSize: number = 250//控件宽度
      @State hSize: number = 100//控件高度
    ​
      build() {
        Column() {
          Button('动画调整按钮宽高')
            .margin(30)
            .width(this.wSize)
            .height(this.hSize)
        }.width('100%').margin({top: 20})
      }
    }
  • 其次,确定控件的始末状态及触发逻辑

    • 一般使用控件监听,并在监听逻辑中对控件状态变量进行二次赋值,从而确定控件的始末状态
    kotlin 复制代码
    @Entry
    @Component
    struct AttrAnimationPage {
      ..................
    ​
      build() {
        Column() {
          Button('动画调整按钮宽高')
            .onClick(() => {//确定控件的始末状态及触发逻辑
              if (this.flag) {
                this.wSize = 150
                this.hSize = 60
              } else {
                this.wSize = 250
                this.hSize = 100
              }
              this.flag = !this.flag // 取反
            })
            .margin(30)
            .width(this.wSize)
            .height(this.hSize)
        }.width('100%').margin({top: 20})
      }
    }
  • 最后,根据需要,确定属性动画作用域及动画参数

    • 属性动画作用域起点:其修饰的控件内的第一行代码
    • 属性动画作用域起点:.animation({ 的上面一行
    less 复制代码
    @Entry
    @Component
    struct AttrAnimationPage {
      ..................
    ​
      build() {
        Column() {
          Button('动画调整按钮宽高')
            .onClick(() => {//属性动画作用域起点
              ..................
            })
            .margin(30)
            .width(this.wSize)
            .height(this.hSize)//属性动画作用域终点
            .animation({
              duration: 2000,//动画的持续时间
              curve: Curve.EaseOut, // 动画的速率 默认值Linear,均速
              iterations: -1,//动画重复次数
              playMode: /*PlayMode.Normal 默认值*/ PlayMode.Alternate//保证开启结束都有动画
            })
        }.width('100%').margin({top: 20})
      }
    }

属性动画的作用域问题

  • 剔除控件高度动画过渡:可将上述代码改为

    • 注意,此时控件的高度将不再受动画修饰

    • 实际效果:

    less 复制代码
    @Entry
    @Component
    struct AttrAnimationPage {
      ..................
    ​
      build() {
        Column() {
          Button('动画调整按钮宽度')
            .onClick(() => {//属性动画作用域起点
              ..................
            })
            .margin(30)
            .backgroundColor(this.btnBackColor)
            .width(this.wSize)//属性动画作用域终点
            .animation({
              ............
            })
            
            .height(this.hSize)//此时,按钮的高度不再被动画所修饰
            
        }.width('100%').margin({top: 20})
      }
    }
  • 多作用域相互覆盖

    • 该动画最终持续时间仍为500ms,虽然说,后面的动画作用域看起来会掩盖前面。但是,属性动画的最终效果遵从就近原则

    • 实际效果:动画的持续时间只有500ms

    yaml 复制代码
    Button('作用域覆盖')
        .onClick(() => {
          this.rotateAngle = 90
        })
        .margin(30)
        .rotate({angle: this.rotateAngle})
        .animation({
          duration: 500,
          curve: Curve.Friction, // 动画的速率,刚开始很快,快结束变慢
          iterations: -1, // 设置-1表示动画无限执行循环
          playMode: PlayMode.Alternate//保证开始结束都有动画
        })
        .animation({
          duration: 2000,
        })
        .animation({
          duration: 4000,
        })
        .animation({
          duration: 6000,
        })
        .animation({
          duration: 10000,
        })

显示动画

显示动画概述

  • 显示动画的最大特点:使用animateTo ({},()=>{}) 的形式

  • 显示动画有什么作用

    • 常用动画参数:用户可以指定什么

      • 参数:动画持续时间、动画播放速度、动画速率曲线、动画延迟执行时长、动画播放次数、动画播放模式、
      • 回调:在动画播放时触发
  • 我们怎么使用显示动画:核心在于确定两个参数

    • 确定代码位置:明确显示动画触发时机
    • 第一个参数:显示动画的基本属性及回调逻辑
    • 第二个参数:动画启动后UI 属性的更新逻辑
  • 细节问题

    • 显示动画对代码的侵入性较高,应优先考虑属性动画

显示动画使用步骤

  • 实现效果:点击后动态调整宽高,且自动触发动画播放结束回调
  • 首先,确定动画的作用对象及相关属性

    • 常用属性:宽高尺寸、摆放状态、控件样式
    • 一般使用@State 修饰控件状态变量,因为其值改变,会自动触发build() 二次执行
    less 复制代码
    @Entry
    @Component
    struct AnimateToPage {
      @State wSize: number = 250//控件宽度
      @State hSize: number = 100//控件高度
    ​
      build() {
        Column() {
          Button('动态调整按钮宽高')
            .margin(30)
            .width(this.wSize)
            .height(this.hSize)
            .onClick(() => {
                ..................
            }
        }.width('100%').margin({top: 20})
      }
    }
  • 其次,确定控件的始末状态及触发逻辑

    • 核心在于补全两个参数

      less 复制代码
      animateTo({},() => {})
    less 复制代码
    @Entry
    @Component
    struct AnimateToPage {
      @State flag: boolean = true
      ..................
    ​
      @State rotateAngle: number = 0
    ​
      build() {
        Column() {
          Button('动态调整按钮宽高')
            .margin(30)
            .width(this.wSize)
            .height(this.hSize)
            
            .onClick(() => {
              if (this.flag) {
                animateTo({//配置显示动画参数,用于动画过渡
                  duration: 2000,
                  curve: Curve.Friction,
                  onFinish: () => {//显示动画结束后回调
                    promptAction.showToast({message: '动画1执行结束了'})
                  }
                }, () => {//显示动画修饰对象的结束状态
                  this.wSize = 150
                  this.hSize = 60
                })
              } else {
                animateTo({}, () => {
                  this.wSize = 250
                  this.hSize = 100
                })
              }
              this.flag = !this.flag//监听标志为取反,支持重复点击
            })
        }.width('100%').margin({top: 20})
      }
    }

显示动画实际使用实例

  • 点击按钮后实现图片动态隐藏及展示

    • 文本框表示当前图像状态,
    • 隐藏逻辑:先旋转再隐藏
    • 显示逻辑:有明显展开
    kotlin 复制代码
    import promptAction from '@ohos.promptAction'
    @Entry
    @Component
    struct AnimateToPage {
    
      @State flag: boolean = true
      @State show: string = 'show'
    
      build() {
        Column() {
          Button(this.show).width(88).height(38).margin(30)
            .onClick(() => {
              animateTo({duration: 2000}, () => {
                // 点击Button的时候 控制 下面的Image的显示与隐藏
                if (this.flag) {
                  this.show = 'hide'
                } else {
                  this.show = 'show'
                }
                this.flag = !this.flag
              })
            })
          if (this.flag) {
            // Image的显示与隐藏 配置不同的 过度效果
            Image($r('app.media.app_icon')).width(300).height(300)
              .transition({type: TransitionType.Insert, scale: {x: 0, y: 1.0}}) // Image出现显示的时候, 渐变缩放的效果
              .transition({type: TransitionType.Delete, rotate: {angle: 180}}) // Image出现隐藏的时候, 选择180°
          }
        }
        .width('100%').margin({top: 20})
      }
    }

路径动画

路径动画概述

  • 概述:路径动画属于显示动画的一种,但此动画不常用,仅做补充
  • 修饰对象:一般用于修饰系统控件,类似按钮等

路径动画使用步骤

  • 设置组件的运动路径。

    • path:位移动画的运动路径,使用svg路径字符串。path中支持使用start和end进行起点和终点的替代,如:'Mstart.x start.y L50 50 Lend.x end.y Z',更多说明请参考绘制路径
    • from:运动路径的起点。取值范围:[0, 1]
    • to:运动路径的终点。取值范围:[0, 1]
    • rotatable:是否跟随路径进行旋转。

路径动画使用实例

  • 点击按钮之后,可观察按钮在水平方向上进行动态移动

  • 实际效果:

less 复制代码
/*路径动画*/
@Entry
@Component
struct PathStudy {
  @State value: boolean = true
​
  build() {
    Column() {
      Button("PathAnimation OK").margin(50)
        // 从 起点移动到 (300/200), 紧接着 再次移动到 (300/500)
        .motionPath({path: 'Mstart.x start.y L300 200 L300 500 Lend.x end.y', from: 0.0, to: 1.0, rotatable:true})
        .onClick(() => {
          animateTo({duration: 6000, curve: Curve.Friction}, () => {
            this.value = !this.value // 通过this.value改变组件的位置
          })
        })
    }.width('100%').height('100%').alignItems(this.value ? HorizontalAlign.Start : HorizontalAlign.Center)
  }
}
相关推荐
xiao-xiang12 分钟前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师28 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳2 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?2 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角9 小时前
CSS 颜色
前端·css
九酒10 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
硬汉嵌入式10 小时前
《安富莱嵌入式周报》第349期:VSCode正式支持Matlab调试,DIY录音室级麦克风,开源流体吊坠,物联网在军工领域的应用,Unicode字符压缩解压
vscode·matlab·开源