鸿蒙Next显示动画animateTo介绍

组件的某些通用属性变化时,可以通过属性动画实现渐变过渡效果,提升用户体验。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。 本文介绍一下以上几个属性各动画的执行效果,并且实现一个简单的点赞功能,看一下演示效果: 源码:

less 复制代码
@Entry
@ComponentV2
struct AnimationTest {
  @Local stackWigth: number = 0;
  @Local stackHeight: number = 0;
  @Local x: number = 0 //旋转轴向量x坐标
  @Local y: number = 0 //旋转轴向量y坐标
  @Local centerX: number = 0 //变换中心点锚点x轴坐标
  @Local centerY: number = 0 //变换中心点锚点y轴坐标
  @Local angle: number = 0 //旋转角度 //正时相对于旋转轴方向顺时针转动
  @Local widthSize: number = 100;
  @Local heightSize: number = 50;
  @Local bgColor: ResourceColor = Color.Green
  @Local opacityChange: number = 1;
  @Local scaleOption: ScaleOptions = {
    x: 1, //x轴的缩放倍数
    y: 1,
    z: 1,
    centerX: 0, //变换中心点x轴坐标
    centerY: 0
  }
  @Local roateOption: RotateOptions = {
    angle: 0
  }
  @Local translateOption: TranslateOptions = {}
  @Local radioBtn1: boolean = false
  @Local radioBtn2: boolean = false
  @Local radioBtn3: boolean = false
  @Local radioBtn4: boolean = false
  @Local radioBtn5: boolean = false
  @Local radioBtn6: boolean = false

  @Local heartOffsetX:number=0
  @Local heartOffsetY:number=0
  @Local heartAngle:number=0
  @Local heartScale:ScaleOptions = {
    x: 1.2,
    y: 1.2,
  }
  @Local heartopacity: number = 0
  @Local animationStop:boolean = true
  build() {
    Column({ space: 10 }) {
      Stack() {
        Button('animation')
          .width(this.widthSize)
          .height(this.heightSize)
          .backgroundColor(this.bgColor)
          .opacity(this.opacityChange)//透明度
          .scale(this.scaleOption)//设置组件缩放
          .rotate(this.roateOption)
          .translate(this.translateOption)
      }.width('100%')
      .height('30%')
      .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => {
        this.stackWigth = newValue.width as number
        this.stackHeight = newValue.height as number
      })


      Row({ space: 5 }) {
        Column() {
          Text('长宽')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn1 = isOn
            })
        }

        Column() {
          Text('背景')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn2 = isOn
            })
        }

        Column() {
          Text('透明度')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn3 = isOn
            })
        }

        Column() {
          Text('缩放')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn4 = isOn
            })
        }

        Column() {
          Text('旋转')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn5 = isOn
            })
        }

        Column() {
          Text('平移')
          Toggle({ type: ToggleType.Checkbox, isOn: false })
            .size({ width: 20, height: 20 })
            .onChange((isOn: boolean) => {
              this.radioBtn6 = isOn
            })
        }
      }

      Column({ space: 10 }) {
        Row({ space: 10 }) {
          Text('X:' + this.x)
          Slider({
            value: this.x,
            min: 0,
            max: this.stackWigth,
            style: SliderStyle.OutSet
          })
            .onChange((value: number) => {
              this.x = value;
            })
        }

        Row({ space: 10 }) {
          Text('Y:' + this.y)
          Slider({
            value: this.y,
            min: 0,
            max: this.stackHeight,
            style: SliderStyle.OutSet
          })
            .onChange((value: number) => {
              this.y = value;
            })
        }

        Row({ space: 10 }) {
          Text('centerX:' + this.centerX)
          Slider({
            value: this.centerX,
            min: 0,
            max: this.stackWigth,
            style: SliderStyle.OutSet
          })
            .onChange((value: number) => {
              this.centerX = value;
            })
        }

        Row({ space: 10 }) {
          Text('centerY:' + this.centerY)
          Slider({
            value: this.centerY,
            min: 0,
            max: this.stackHeight,
            style: SliderStyle.OutSet
          })
            .onChange((value: number) => {
              this.centerY = value;
            })
        }

        Row({ space: 10 }) {
          Text('angle:' + this.angle)
          Slider({
            value: this.angle,
            min: -180,
            max: 180,
            style: SliderStyle.OutSet
          })
            .onChange((value: number) => {
              this.angle = value;
            })
        }
      }.width('80%')

      Row() {
        Button('执行').onClick(() => {
          this.getUIContext().animateTo({
            duration: 3000, //动画持续时间,单位为毫秒
            curve: Curve.EaseOut, //动画曲线
            delay: 100, //动画延迟播放时间,单位为ms(毫秒)
            iterations: 1, //动画播放次数
            playMode: PlayMode.Normal, //动画播放模式 正向
            onFinish: () => { //动画播放完成回调

            }
          }, () => {
            if (this.radioBtn1) {
              this.widthSize = 200
              this.heightSize = 50
            }
            if (this.radioBtn2) {
              this.bgColor = Color.Red
            }
            if (this.radioBtn3) {
              this.opacityChange = 0.3
            }
            if (this.radioBtn4) {
              this.scaleOption = {
                x: 1.5, //x轴的缩放倍数
                y: 1.5,
                z: 1,
                centerX: 0, //变换中心点x轴坐标
                centerY: 0
              }
            }
            if (this.radioBtn5) {
              this.roateOption = {
                x: this.x,
                y: this.y,
                angle: this.angle,
                centerX: this.centerX,
                centerY: this.centerY
              }
            }
            if (this.radioBtn6) {
              this.translateOption = {
                x: 100,
                y: 100
              }
            }
          })
        })

        Button('恢复').onClick(() => {
          this.widthSize = 100;
          this.heightSize = 50;
          this.bgColor = Color.Green
          this.opacityChange = 1;
          this.scaleOption = {
            x: 1, //x轴的缩放倍数
            y: 1,
            z: 1,
            centerX: this.centerX, //变换中心点x轴坐标
            centerY: this.centerY
          }
          this.roateOption = {
            angle: 0
          }
          this.translateOption = {
            x: 0,
            y: 0
          }
        })
      }

      Stack({alignContent:Alignment.Start}) {
        Text('点赞动画').fontSize(30)
        Image($r('app.media.heart')).width(40).height(40)
          .rotate({angle:this.heartAngle})
          .position({
            x: this.heartOffsetX,
            y: this.heartOffsetY
          })
          .opacity(this.heartopacity)
          .scale(this.heartScale)
      }.layoutWeight(1).width('100%').backgroundColor(Color.Yellow)
      .gesture(
        TapGesture({ count: 2 })
          .onAction((event: GestureEvent) => {
            if (!this.animationStop) return
            this.animationStop=false
            this.heartOffsetX = event.fingerList[0].localX
            this.heartOffsetY = event.fingerList[0].localY
            this.heartopacity=1
            this.heartAngle=(Math.random()*2-1)*50
            setTimeout(()=>{
              this.getUIContext().animateTo({
                duration: 500, //动画持续时间,单位为毫秒
                curve: Curve.EaseOut, //动画曲线
                iterations: 1, //动画播放次数
                playMode: PlayMode.Normal, //动画播放模式 正向
                onFinish: () => { //动画播放完成回调
                  this.getUIContext().animateTo({
                    duration: 1000, //动画持续时间,单位为毫秒
                    curve: Curve.EaseOut, //动画曲线
                    iterations: 1, //动画播放次数
                    playMode: PlayMode.Normal, //动画播放模式 正向
                    onFinish: () => { //动画播放完成回调
                      this.heartScale = {
                        x: 1.2,
                        y: 1.2,
                      }
                      this.animationStop = true
                    }
                  },()=>{
                    this.heartScale = {
                      x: 2,
                      y: 2,
                    }
                    this.heartopacity = 0
                  })
                }
              },()=>{
                this.heartScale = {
                  x: 1,
                  y: 1,
                }
              })
            },100)
          })
      )
    }
  }
}
相关推荐
呆dai~1 小时前
基于原生能力的键盘控制
harmonyos·鸿蒙
Sally璐璐3 小时前
HarmonyOS开发利器:ArkTS全解析
华为·harmonyos
移动端开发者5 小时前
鸿蒙Next使用AudioCapturer实现音频录制和AI语言转文字
harmonyos
移动端开发者5 小时前
鸿蒙Next选择按钮Toggle、Checkbox、Radio介绍
harmonyos
彭不懂赶紧问11 小时前
鸿蒙NEXT开发浅进阶到精通13:鸿蒙开发项目中遇到的问题及解决笔记04
前端·harmonyos
Aisanyi1 天前
【鸿蒙开发】适配深浅色模式
前端·harmonyos
暗雨1 天前
鸿蒙游戏引擎 Godot 测试与发布全流程指南(HarmonyOS 5+)
harmonyos