HarmonyOS 显式动画animateTo()

基础使用

  • 第1步和第2步与属性动画相同
  • 3.animateTo()传递两个参数,第一个参数是对象,和属性动画一样,第二个参数是回调函数,回调函数中执行属性变化
@Entry
@Component
struct Index {
  @State scaleX: number = 1
  @State scaleY: number = 1

  build() {
    Text()
      .width(50).height(50).backgroundColor(Color.Red)
      .scale({ x: this.scaleX,  y: this.scaleY })   // 1 who ✅
      .onClick(()=>{  // 2 find&fixed 🔍 💕
        animateTo({duration: 2000,curve: Curve.EaseOut,iterations: 3},()=>{
          this.scaleX = 2
          this.scaleY = 2
        })
      })
  }
}

实战案例1: 基础案例

  • 示例效果1
@Entry
@Component
struct Index {
  @State x: number = 0
  @State y: number = 0

  build() {
    Column() {
      Row()
        .width(100)
        .height(100)
        .backgroundColor(Color.Red)
        .translate({
          x: this.x,
          y: this.y
        })
        .onClick(() => {
          // 1 左上角 -> 右上角
          animateTo({
            onFinish: () => {
              // 2 右上角 -> 右下角
              animateTo({
                onFinish: () => {
                  // 3 右下角 -> 左下角
                  animateTo({
                    onFinish: () => {
                      // 4 左下角 -> 左上角
                      animateTo({}, () => {
                        this.x = 0
                        this.y = 0
                      })
                    }
                  }, () => {
                    this.x = 0
                    this.y = 100
                  })
                }
              }, () => {
                this.x = 100
                this.y = 100
              })
            }
          }, () => {
            this.x = 100
            this.y = 0
          })
        })
    }
    .width("100%")
    .height("100%")
    .alignItems(HorizontalAlign.Start)
  }
}
  • 示例效果2
@Entry
@Component
struct Index {
  @State scaleVal: number = 1.0

  build() {
    Column() {
      Text('点我跳动!')
        .fontSize(18)
        .padding(12)
        .backgroundColor('#4A90E2')
        .borderRadius(12)
        .scale({ x: this.scaleVal, y: this.scaleVal })
        .onClick(() => {
          this.animate()
        })
    }
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .height('100%')
  }

  animate() {
    animateTo({
      duration: 100,
      curve: Curve.EaseInOut,
      onFinish: () => {

        animateTo({
          duration: 100,
          curve:
          Curve.EaseInOut,
          onFinish: () => {

            animateTo({ duration: 100, curve: Curve.EaseInOut }, () => {
              this.scaleVal = 1.0
            })
          }
        }, () => {
          this.scaleVal = 0.9

        })
      }
    }, () => {
      this.scaleVal = 1.2
    })
  }
}

实战案例2: 高铁出发地与目的地切换案例

http://tmp00002.zhaodashen.cn/827597275c0f263b9eab88cc0640d9ae.jpg

@Entry
@Component
struct Index {
  @State isRes: boolean = true

  build() {
    Column() {
      Flex({
        direction: this.isRes ? FlexDirection.Row : FlexDirection.RowReverse,   // 1 who ✅
        justifyContent: FlexAlign.SpaceBetween
      }) {
        Text('北京').fontColor('#fff')
        Text('切换').fontColor('#fff')
          .rotate({angle: this.isRes ? 0 : 360})  // 1 who ✅
          .onClick(() => {
            // 2 find 🔍 & fixed  💕
            animateTo({ duration: 1000, playMode: this.isRes ? PlayMode.Normal : PlayMode.Alternate }, () => {
              this.isRes = !this.isRes
            })
          })
        Text('上海').fontColor('#fff')
      }.width('100%')
    }.width('100%').height('100%').backgroundColor('#000').justifyContent(FlexAlign.Center).padding({left: 20,right: 20})
  }
}

实战案例3:提交表单错误抖动

import curves from "@ohos.curves"


@Entry
@Component
export struct Index {
  @State textPhone: string = ''
  @State doScale: ScaleOptions = { x: 1, y: 1 }

  startAnimation() {
    animateTo({
      duration: 800,
      // 应用`curves.springCurve`生成的Spring Curve动画曲线,模拟物理弹簧效果
      curve: curves.springCurve(0, 10, 80, 10),
      iterations: 1,
    }, () => {
      this.doScale = { x: 1.1, y: 1.1 };
    })
    this.doScale = { x: 1, y: 1 };
  }

  build() {
    Column() {
      TextInput({ text: $$this.textPhone, placeholder: '请输入手机号' })
        .margin({ top: 30 })
          // .padding({ left: 0 })
        .width('658lpx')
        .height('96lpx')
        .scale(this.doScale)
        .backgroundColor(Color.White)
        .type(InputType.PhoneNumber)
        .maxLength(13)
        .placeholderColor("#CBCBCB")
        .fontColor("#2E2E2E")
        .fontSize('36lpx')
        .caretColor('#FF1919')
        .borderRadius(40)

      Button('动画测试').margin({ top: 30 }).onClick(() => {
        this.startAnimation()
      })
    }.width('100%').height('100%')
    .backgroundColor("#f5f5f5")
  }
}

实战案例4:动态菜单

https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_NEXT-Animation

鸿蒙开发者班级

posted @ 2025-11-27 12:58  神龙教主  阅读(2)  评论(0)    收藏  举报