HarmonyOS ArkUI 属性动画入门详解

news/2024/7/21 8:07:27 标签: harmonyos, 华为

HarmonyOS ArkUI 属性动画入门详解

  • 前言
  • 属性动画是什么?
    • 我们借助官方的话来说,
    • 我们自己简单归纳下
  • 参数解释
  • 举个例子
    • 旋转动画
  • 位移动画
  • 组合动画
  • 总结

前言

鸿蒙OS最近吹的很凶,赶紧卷一下。学习过程中发现很多人吐槽官方属性动画这一章比较敷衍,我第一遍也看的半懂不懂的,所以就有了这篇文章,在官方的介绍基础上补充了自己的理解

属性动画是什么?

我们借助官方的话来说,

属性动画,是最为基础的动画,其功能强大、使用场景多,应用范围较广。常用于如下场景中:

一、页面布局发生变化。例如添加、删除部分组件元素。
二、页面元素的可见性和位置发生变化。例如显示或者隐藏部分元素,或者将部分元素从一端移动到另外一端。
三、页面中图形图片元素动起来。例如使页面中的静态图片动起来。
简单来说,属性动画是组件的通用属性发生改变时而产生的属性渐变效果。如下图所示,其原理是,当组件的通用属性发生改变时,组件状态由初始状态逐渐变为结束状态的过程中,会创建多个连续的中间状态,逐帧播放后,就会形成属性渐变效果,从而形成动画。

在这里插入图片描述
属性动画的使用方式也非常简单,只需要给组件(包括基础组件和容器组件)添加animation属性,并设置好参数,如下代码所示:

Image($r('app.media.image1'))   
   .animation({   
      duration: 1000,    
      tempo: 1.0,    
      delay: 0,    
      curve: Curve.Linear,    
      playMode: PlayMode.Normal,    
      iterations: 1  
   })

别急哈,等你把上面这个代码贴上去,你就会发现上例代码并没有动画,这是因为

1、animation属性作用域。animation自身也是组件的一个属性,其作用域为animation之前。即产生属性动画的属性须在animation之前声明,其后声明的将不会产生属性动画。以示例中的五个图标动画为例,我们期望产生动画的属性为Image组件的width属性,故该属性width需在animation属性之前声明。如果将该属性width在animation之后声明,则不会产生动画效果。

2、产生属性动画的属性变化时需触发UI状态更新。在上面的示例中,因为缺少产生动画的属性,所以并不会有动画

3、产生属性动画的属性本身需满足一定的要求,并非任何属性都可以产生属性动画。目前支持的属性包括width、height、position、opacity、backgroundColor、scale、rotate、translate等

我们自己简单归纳下

属性动画 = 属性 + a n i m a t i o n (属性作用域) 属性动画 = 属性 + animation (属性作用域) 属性动画=属性+animation(属性作用域)

这个属性就是目前支持的width、height、position、opacity、backgroundColor、scale、rotate、translate等

参数解释

属性名称属性类型默认值描述
durationnumber1000动画时长,单位为毫秒,默认时长为1000毫秒。
temponumber1.0动画的播放速度,值越大动画播放越快,值越小播放越慢,为0时无动画效果。
curveCurveCurve.Linear动画变化曲线,默认曲线为线性。
delaynumber0延时播放时间,单位为毫秒,默认不延时播放。
iterationsnumber1播放次数,默认一次,设置为-1时表示无限次播放。
playModePlayModePlayMode.Normal设置动画播放模式,默认播放完成后重头开始播放。
onFinishfunction-动画播放结束时回调该函数。

其中变化曲线curve枚举值为:

名称描述
Linear表示动画从头到尾的速度都是相同的。
Ease表示动画以低速开始,然后加快,在结束前变慢,CubicBezier(0.25, 0.1, 0.25, 1.0)。
EaseIn表示动画以低速开始,CubicBezier(0.42, 0.0, 1.0, 1.0)。
EaseOut表示动画以低速结束,CubicBezier(0.0, 0.0, 0.58, 1.0)。
EaseInOut表示动画以低速开始和结束,CubicBezier(0.42, 0.0, 0.58, 1.0)。
FastOutSlowIn标准曲线,cubic-bezier(0.4, 0.0, 0.2, 1.0)。
LinearOutSlowIn减速曲线,cubic-bezier(0.0, 0.0, 0.2, 1.0)。
FastOutLinearIn加速曲线,cubic-bezier(0.4, 0.0, 1.0, 1.0)。
ExtremeDeceleration急缓曲线,cubic-bezier(0.0, 0.0, 0.0, 1.0)。
Sharp锐利曲线,cubic-bezier(0.33, 0.0, 0.67, 1.0)。
Rhythm节奏曲线,cubic-bezier(0.7, 0.0, 0.2, 1.0)。
Smooth平滑曲线,cubic-bezier(0.4, 0.0, 0.4, 1.0)。
Friction阻尼曲线,CubicBezier(0.2, 0.0, 0.2, 1.0)。

人话解释:相同时间,结果相同,不同的过程

播放模式playMode枚举值为:

名称描述
Normal动画按正常播放。
Reverse动画反向播放。
Alternate动画在奇数次(1、3、5…)正向播放,在偶数次(2、4、6…)反向播放。
AlternateReverse动画在奇数次(1、3、5…)反向播放,在偶数次(2、4、6…)正向播放。

注意onFinish回调函数与参数iterations有关。当参数iterations播放结束时,会调用onFinish函数来进行后续的业务处理。而当iterations设置为-1时,表示无限次播放,则onFinish回调函数不会被调用。

举个例子

旋转动画

@State rotateAngle : number = 0
...
  Text("旋转动画")

      Row(){
            Button("旋转动画开始",{type: ButtonType.Capsule,stateEffect:true})
              .onClick(()=>{
                this.rotateAngle =360
              })

            Image($r('app.media.loading'))
              .width(100)
              .height(100)
              .rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
              .animation({
                duration: 2000,
                tempo: 1.0,
                delay: 0,
                curve: Curve.Linear,
                playMode: PlayMode.Normal,
                iterations: -1
              })
      }
      .height("30%")
      .width("100%")
      .backgroundColor(Color.Green)

上例可以看到,添加了rotate旋转作用域,和animation作用域,并通过rotateAngle 状态的改变控制了动画的开始,效果如下
在这里插入图片描述

位移动画

  @State xState : number = 0
  @State yState : number = 0
...
 Text("位移动画")

      Row(){

            Text('HarmonyOS')
              .width(200)
              .height(100)
              .fontColor(Color.Blue)
              .fontSize(30)
              .fontStyle(FontStyle.Italic)
              .fontWeight(FontWeight.Bold)
              .fontFamily('Arial')
              .margin(100)
              .position({x: this.xState,y:this.yState})
              .animation({
                duration: 1000,
                tempo: 1.0,
                delay: 0,
                curve: Curve.Linear,
                playMode: PlayMode.Normal,
                iterations: 1,
                onFinish:()=>{
                  if ( this.xState == 0) {
                    this.xState =100
                    this.yState =100
                  }else {
                    this.xState =0
                    this.yState =0
                  }
                }
              })
      }
      .height("30%")
      .width("100%")
      .backgroundColor(Color.Yellow)

上例我们可以看到,通过设置position和animation实现了位移动画,并且在其到达指定路径的onFinish回调中重新设置了xState 和yState ,以达到一种另类的永久动画效果。运行效果如下
在这里插入图片描述

组合动画

并不是一次只能加一个属性,也可以多个一起加

  @State watermelonRotateAngle : number = 0
  @State width : number = 50
  @State height : number = 50
  ...


Text("组合动画")

      Row(){

        Button("组合动画开始",{type: ButtonType.Capsule,stateEffect:true})
          .onClick(()=>{
            this.watermelonRotateAngle =360
            this.width = 100
            this.height = 100
          })

        Image($r('app.media.watermelon'))
          .width(this.width)
          .height(this.height)
          .rotate({ x: 0, y: 0, z: 1, angle: this.watermelonRotateAngle })
          .animation({
            duration: 2000,
            tempo: 1.0,
            delay: 0,
            curve: Curve.Linear,
            playMode: PlayMode.Normal,
            iterations: -1
          })

      }
      .height("40%")
      .width("100%")
      .backgroundColor(Color.Orange)
  

上面我们有三个属性动画,分别是width ,height和 rotate,效果如下

在这里插入图片描述

总结

参考:HarmonyOS第一课
教程跟以前比来说丰富了很多,也比较系统。所以博主只会在比官方现在教程比较笼统或自己觉得理解比较晦涩的地方进行单篇输出,不会像Compose一样边学变更新了。如果对Compose有兴趣可以看看我的Jetpack Compose入门详解(实时更新)

吐槽一下:官方文档属性动画文档写的是真的敷衍,给人一种我都讲了你不懂是你的事情的感觉(当然,可能是我比较菜)


http://www.niftyadmin.cn/n/4964528.html

相关文章

内网隧道代理技术(十七)之 NPS的使用

NPS的介绍和使用 NPS介绍 nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发,可支持任何tcp、udp上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还支持内网http代理、内网socks5代理、p2p等,…

内网穿透与异地组网解析

随着全球化和数字化的发展,越来越多的企业需要在不同地理位置之间建立网络连接。为了实现企业组网这一目标,企业一般采用内网穿透或异地组网的技术来实现,究竟这两种技术有什么区别呢? 什么是内网穿透? 内网穿透是通过…

Java SDK 性能测试代码配置及实操

测试方案 由于 Java SDK 无法单独使用,我们无法直接采集其性能相关数据。因此我们需要设计出对照试验,来对比集成前后,性能数据差异。 首先我们需要开发一个简单的服务程序,其对外暴露的接口,分别验证相同并发&#…

FPGA功能及特点

集成电路芯片包括数字芯片和模拟芯片两大类,数字芯片又分为存储器芯片和逻辑芯片。 逻辑芯片一般包括CPU、GPU、DSP等通用处理器芯片以及专用集成电路芯片ASIC。 FPGA(现场可编程门阵列)就是逻辑芯片的一种。 FPGA功能 FPGA中文名是现场可…

Nuxt3环境变量配置

Nuxt3 正式发布还不到半年,在投入生产环境使用后,遇到了不少问题,很难找到合适的解决方案,其中环境变量配置就是其中一个,之前一直未能解决,最近要上持续集成,无法绕过这个问题,所以…

软考高级系统架构设计师系列论文六十九:论信息系统的安全风险评估

一、信息系统相关知识点 软考高级信息系统项目管理师系列之四十三:信息系统安全管理软考高级系统架构设计师:系统安全分析与设计

7.Oracle视图创建与使用

1、视图的创建与使用 在所有进行的SQL语句之中,查询是最复杂的操作,而且查询还和具体的开发要求有关,那么在开发过程之中,程序员完成的并不是是和数据库的所有内容,而更多的是应该考虑到程序的设计结构。可以没有一个项…

C#|如何调试进依赖动态库中

第一步:打开项目属性 第二步 打开debug的本地调试可用 第三步 把要调试的代码拖进主界面打断点就可以进断点了