HarmonyOS-基础之动画

1、是什么?

动画可以在UI界面发生变化时,提供渐变过渡效果,提升用户体验。
动画的实现原理是通过在一段时间内连续播放一系列静止画面(帧),从而产生流畅的视觉效果。

ArkUI 提供了多种动画接口,例如:显式动画、属性动画、转场动画等,来实现各种动画效果。

2、显示动画

  • animateTo()是ArkUI 提供的一个全局的动画函数,调用此函数实现的动画称为显式动画
animateTo(value: AnimateParam, event: () => void): void
  • 该函数共有两个参数,分别是
    • 动画参数,用于设置动画时长、属性值变化曲线等等。
    • 匿名函数,用于设置属性值的终点值,在该函数中设置的属性值,系统均会按照前边设置的动画参数,驱动属性值从其初始值平滑的过渡到终点值,从而实现动画效果。
显示动画案例
@Entry
@Component
struct Index {
  @State marginLeft: number | string = '0'
  @State opacityNum: number = 1
  @State scaleX: number = 1
  @State scaleY: number = 1
  @State rotateNum: number = 0
  @State opacityNum2: number = 1

  build() {
    Column() {
      Text('这是一段文本,用来测试动画')
        .fontSize(30)
        .fontWeight(700)
        .width('100%')
        .textAlign(TextAlign.Center)
        .margin({ left: this.marginLeft })
          // 透明度
        .opacity(this.opacityNum)

      Text('显示动画2')
        .fontSize(30)
        .fontWeight(700)
        .width('100%')
        .textAlign(TextAlign.Center)
          // 缩放
        .scale({ x: this.scaleX, y: this.scaleY })
          // 旋转
        .rotate({ angle: this.rotateNum })
        .opacity(this.opacityNum2)

      Button('显示动画').onClick(() => {
        /**
         * animateTo:内部全局组件
         *  - duration : 动画时间
         *  - curve : 动画速度
         */
        animateTo({ duration: 1000, curve: Curve.Linear }, () => {
          // 显示动画一
          if (this.marginLeft == 0) {
            this.marginLeft = '-100%'
            this.opacityNum = 0
          } else {
            this.marginLeft = 0
            this.opacityNum = 1
          }

          // 显示动画二
          if (this.rotateNum == 0) {
            this.scaleX = 0
            this.scaleY = 0
            this.rotateNum = 360
            this.opacityNum2 = 0
          } else {
            this.scaleX = 1
            this.scaleY = 1
            this.rotateNum = 0
            this.opacityNum2 = 1
          }
        })
      })
    }.width('100%')
  }
}

image

3、属性动画

animation()是ArkUI提供的组件的属性方法,调用此函数实现的动画称为属性动画
注意 :animation()属性方法必须放在动态动画属性之后

@Entry
@Component
struct Index {
  @State marginLeft: number | string = 0
  @State opacityNum: number = 1

  build() {
    Column() {

      Text('属性动画1')
        // .animation({ duration: 1000, curve: Curve.EaseOut }) // 错误写法
        .fontSize(30)
        .fontWeight(700)
        .width('100%')
        .textAlign(TextAlign.Center)
        .margin({ left: this.marginLeft })
        .opacity(this.opacityNum)
        .animation({ duration: 1000, curve: Curve.EaseOut })

      Button('属性动画').onClick(() => {
        if (this.opacityNum == 1) {
          this.marginLeft = '-100%'
          this.opacityNum = 0
        }else{
          this.opacityNum = 1
          this.marginLeft = 0
        }
      })

    }.width('100%')
  }
}

image

4、页面内的转场动画

转场动画是指组件出现或消失时的过渡动画。ArkUI 专门提供了transition接口来配置转场动画效果,可以定义平移、透明度、旋转、缩放这几种转场样式的单个或者组合的转场效果。

transition(value: TransitionOptions)

注意 :transition 必须配合着 animateTo 一起使用才有效

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

  build() {
    Column() {
      if (this.isActive) {
        Text('转场动画')
          .textAlign(TextAlign.Center)
          .width('100%')
          .fontSize(30)
          .fontWeight(700)
            // 设置离开动画
          .transition({ type: TransitionType.Delete, opacity: 0, translate: { x: '-100%' } })
            // 设置进入动画
          .transition({ type: TransitionType.Insert, opacity: 0, translate: { x: '-100%' } })
      }
      
      // 注意 :transition 必须配合着 animateTo 一起使用才有效

      Button('转场动画').onClick((event: ClickEvent) => {
        animateTo({ duration: 1000, curve: Curve.Linear }, () => {
          this.isActive = !this.isActive
        })
      })
    }.width('100%')
    .padding(20)
  }
}

image

5、页面间的转场动画

  • 除了页面内的动画,我们还可以实现页面间转场动画
  • 在push跳转路由及返回上一个路由页面时,默认就有转场动画
  • HarmonyOS也提供了自定义的页面间的转场动画语法
页面A
import router from '@ohos.router'

@Entry
@Component
struct Index {
  pageTransition() {
    // A页面离开动画
    PageTransitionExit({
      type: RouteType.Push,
      duration: 2000,
      curve: Curve.FastOutLinearIn
    }).slide(SlideEffect.Top)

    // A页面进入动画
    PageTransitionEnter({
      type: RouteType.Pop,
      duration: 1000,
      curve: Curve.EaseIn
    }).slide(SlideEffect.Left)
  }

  build() {
    Column() {
      Text('这是页面 =====A=====')
        .fontSize(30)
        .fontWeight(700)
        .width('100%')

      Button('去页面B').onClick((event: ClickEvent) => {
        router.pushUrl({ url: 'pages/demo04/animation/AnimationPage02', params: { id: 1 } })
      })
    }.width('100%')
    .padding(10)
  }
}
页面B
import router from '@ohos.router'

@Entry
@Component
struct Index {
  // 页面转场动画方法组件
  pageTransition() {
    // B页面离开动画
    PageTransitionExit({
      type: RouteType.None,
      duration: 1500,
      curve: Curve.EaseOut
    }).slide(SlideEffect.Right)

    // B页面进入动画
    PageTransitionEnter({
      type: RouteType.Pop,
      duration: 2500,
      curve: Curve.ExtremeDeceleration
    }).slide(SlideEffect.Bottom)
  }

  build() {
    Column() {
      Text('这是页面 *******B*******')
        .fontSize(30)
        .fontWeight(700)
      Button('返回页面A').onClick((event: ClickEvent) => {
        console.log('获取A页面传递的路由参数:' + JSON.stringify(router.getParams()))
        router.back()
      })
    }.width('100%')
    .padding(10)
  }
}

image

posted @ 2024-04-16 23:17  我也有梦想呀  阅读(95)  评论(0)    收藏  举报