我最近用 ArkUI-X 实现了一组 "会跳舞的 UI",从弹性按钮到双人舞组合动画,让组件们灵活起来

包含功能

✅ 弹性按钮:点击后像弹簧一样回弹
✅ 图片缩放:加载时自动收缩表演
✅ 路径动画:图标沿着自定义路线 "蛇形走位"
✅ 旋转文字:360° 旋转停不下来
✅ 组动画:按钮集体跳机械舞
✅ 双人舞:图片与文字同步旋转平移

踩坑指南:动画开发避坑三要素

  1. 状态管理

    • ❌ 错误做法:直接修改样式属性(如.rotate(360)
    • ✅ 正确姿势:通过@State变量控制,ArkUI-X 会自动触发动画
  2. 路径坐标

    • ❌ 错误写法:path: 'Mstart.x start.y...'(未定义变量)
    • ✅ 正确示例:path: 'M0 0 L300 200 L300 500 L500 500'
  3. 性能优化

    • 使用Curve曲线(如EaseInOut)替代线性动画
    • 复杂动画建议用AnimatorGroup分组控制

直接上代码:

@Entry
@Component
struct ArkUIXAnimationExample {
  @State isButtonScaled: boolean = false
  @State imgScaleValue: number = 1
  @State rotationAngle: number = 0
  @State pathProgress: number = 0
  @State toggle: boolean = true
  @State isTextRotating: boolean = false
  @State isTextAnimated: boolean = false

  build() {
    Column({ space: 50 }) {
      // 弹性按钮
      Button('点我试试')
        .width(150)
        .height(50)
        .scale({
          x: this.isButtonScaled ? 1.2 : 1,
          y: this.isButtonScaled ? 1.2 : 1
        })
        .animation({
          duration: 800,
          curve: Curve.EaseInOut
        })
        .onClick(() => {
          animateTo({ duration: 200 }, () => {
            this.isButtonScaled = !this.isButtonScaled
          })
        })

      // 图片缩放
      Image($rawfile('home/poster1.png'))
        .width(200)
        .height(200)
        .scale({ x: this.imgScaleValue, y: this.imgScaleValue })
        .animation({
          duration: 600,
          curve: Curve.Linear,
          delay: 200
        })
        .onAppear(() => {
          this.imgScaleValue = 0.8
        })

      // 路径动画
      Button('click me').margin(50)
        .motionPath({
          path: 'Mstart.x start.y L300 200 L300 500 Lend.x end.y',
          from: 0.0,
          to: 1.0,
          rotatable: true
        }) // 执行动画:从起点移动到(300,200),再到(300,500),再到终点
        .onClick(() => {
          animateTo({ duration: 4000, curve: Curve.Linear }, () => {
            this.toggle = !this.toggle // 通过this.toggle变化组件的位置
          })
        })


      // 旋转文字
      Button('旋转文字')
        .fontSize(18)
        .rotate({ angle: this.isTextRotating? 360 : 0 })
        .animation({
          duration: 3000,
          curve: Curve.EaseInOut,
          iterations: Infinity,
          playMode: PlayMode.Normal
        })
        .onClick(() => {
          this.isTextRotating = true
        })

      // 按钮组动画
      Row() {
        ForEach(['按钮1', '按钮2', '按钮3'], (label: string, index: number) => {
          Button(label)
            .width(100)
            .height(50)
            .translate({ x: index * 120 })
            .rotate({ angle: 30 * index })
            .animation({
              duration: 1000 + index * 200,
              curve: Curve.EaseInOut
            })
        })
      }

      // 组合动画
      Stack({ alignContent: Alignment.Center }) {
        Image($rawfile('home/poster3.png'))
          .width(150)
          .height(150)
          .rotate({ angle: this.isTextAnimated? 180 : 0 })
          .animation({
            duration: 2000,
            curve: Curve.Ease,
            playMode: PlayMode.Normal
          })

        Text('伴舞文字')
          .fontSize(20)
          .translate({ x: this.isTextAnimated? -50 : 0 })
          .animation({
            duration: 2000,
            curve: Curve.Ease,
            playMode: PlayMode.Normal
          })
          .onClick(() => {
            this.isTextAnimated = !this.isTextAnimated
          })
      }
    }
    .width('100%').alignItems(this.toggle ? HorizontalAlign.Start : HorizontalAlign.Center)
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐