鸿蒙系列--属性动画

发布时间:2024年01月10日

一、定义

当组件的通用属性发生改变时而产生的属性渐变效果

说明:

????????当组件的通用属性发生改变时,组件状态由初始状态逐渐变为结束状态的过程中,会创建多个连续的中间状态,逐帧播放后,就会形成动画

二、创建

给组件(如lmage、Button、 Column等)添加animation属性,并设置属性动画的参数

参数:

  • duration:动画时长,单位为毫秒,默认时长为1000毫秒
  • tempo:动画的播放速度,值越大动画播放越快,值越小播放越慢,为0时无动画效果,默认值:1
  • curve:动画变化曲线,默认曲线为线性,默认值是:Curve.Linear

名称

描述

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)。

  • delay:延时播放时间,单位为毫秒,默认值:0,不延时播放
  • iterations:播放次数,默认值:1,设置为-1时表示无限次播放
  • playMode:设置动画播放模式,默认:播放完成后重头开始播放

名称

描述

Normal

动画按正常播放

Reverse

动画反向播放

Alternate

动画在奇数次(1、3、5...)正向播放,在偶数次(2、4、6...)反向播放

AlternateReverse

动画在奇数次(1、3、5...)反向播放,在偶数次(2、4、6...)正向播放

  • onFinish:动画播放结束时回调?

三、使用:

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

发现动画并未执行,原因可能如下:

  • 产生属性动画的属性需要在animation之前声明
  • 产生属性动画的属性变化时需触发UI状态更新
  • 产生属性动画的属性本身需满足一定的要求,并非任何属性都可以产生属性动画。目前支持的属性包括width、height、position、opacity、backgroundColor、scale、rotate、translate等

三、案例

旋转动画?rotate

@Entry
@Component
struct AnimPage {
  @State rotateAngle: number = 0

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

        Row({ space: 20 }) {
          //沿着X轴旋转
          Image($r('app.media.app_icon'))
            .width(80)
            .height(80)
            .rotate({ x: 1, y: 0, z: 0, angle: this.rotateAngle })
            .animation({
              duration: 2000,
              tempo: 1.0,
              delay: 0,
              curve: Curve.Linear,
              playMode: PlayMode.Normal,
              iterations: -1
            })

          //沿着Y轴旋转
          Image($r('app.media.app_icon'))
            .width(80)
            .height(80)
            .rotate({ x: 0, y: 1, z: 0, angle: this.rotateAngle })
            .animation({
              duration: 2000,
              tempo: 1.0,
              delay: 0,
              curve: Curve.Linear,
              playMode: PlayMode.Normal,
              iterations: -1
            })

          //沿着Z轴旋转
          Image($r('app.media.app_icon'))
            .width(80)
            .height(80)
            .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
            })

          Image($r('app.media.app_icon'))
            .width(80)
            .height(80)
            .rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
            .animation({
              duration: 2000,
              tempo: 1.0,
              delay: 0,
              //低速开始,然后加快,在结束前变慢
              curve: Curve.Ease,
              //
              playMode: PlayMode.Reverse,
              iterations: -1
            })
        }
        .margin({ top: 20 })
        .padding({ left: 10 })
        .height("30%")
        .width("100%")
        .backgroundColor(Color.Red)

      }
      .width('100%')
    }
    .height('100%')
  }
}

位移动画?position

@Entry
@Component
struct AnimPage {
  @State xState: number = 0
  @State yState: number = 0

  build() {
    Row() {
      Column() {
        Row() {
          Text('位移动画')
            .width(200)
            .height(100)
            .fontColor(Color.Blue)
            .fontSize(30)
            .margin(100)
            .position({ x: this.xState, y: 0 })
            .animation({
              duration: 1000,
              tempo: 1.0,
              delay: 0,
              curve: Curve.Linear,
              playMode: PlayMode.Normal,
              iterations: 1,
              onFinish: () => {
                this.xState = 200
              }
            })

          Image($r('app.media.app_icon'))
            .width(80)
            .height(80)
            .position({ x: 0, y: this.yState })
            .animation({
              duration: 1000,
              tempo: 1.0,
              delay: 0,
              curve: Curve.Linear,
              playMode: PlayMode.Normal,
              iterations: 1,
              onFinish: () => {
                //在onFinish回调中重新设置了xState和yState,也可以实现永久播放的效果
                if (this.yState == 0) {
                  this.yState = 200
                } else {
                  this.yState = 0
                }
              }
            })
        }
        .height("30%")
        .width("100%")
        .backgroundColor(Color.Red)
      }
      .width('100%')
    }
    .height('100%')
  }
}

缩放动画?width、height

@Entry
@Component
struct AnimPage {
  @State widthSize: number = 250
  @State heightSize: number = 100
  @State flag: boolean = true

  build() {
    Row() {
      Column() {
        Button('缩放')
          .onClick(() => {
            if (this.flag) {
              this.widthSize = 150
              this.heightSize = 60
            } else {
              this.widthSize = 250
              this.heightSize = 100
            }
            this.flag = !this.flag
          })
          .margin(30)
          .width(this.widthSize)
          .height(this.heightSize)
          .animation({
            duration: 2000,
            curve: Curve.EaseOut,
            iterations: 3,
            playMode: PlayMode.Normal
          })

      }.width('100%')
      .height('30%')
      .backgroundColor(Color.Red)
    }
    .width('100%')
    .height('100%')
  }
}

透明度动画?opacity

@Entry
@Component
struct AnimPage {
  @State opacityAngle: number = 1

  build() {
    Row() {
      Column() {
        Button('透明度')
          .onClick(() => {
            this.opacityAngle = 0
          })
          .margin(50)
          .opacity(this.opacityAngle)
          .animation({
            duration: 2000,
            curve: Curve.Friction,
            delay: 500,
            iterations: -1, // 设置-1表示动画无限循环
            playMode: PlayMode.Alternate
          })

      }.width('100%')
      .height('30%')
      .backgroundColor(Color.Red)
    }
    .width('100%')
    .height('100%')
  }
}

文章来源:https://blog.csdn.net/weixin_42277946/article/details/135495361
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。