当前位置:   article > 正文

HarmonyOS4-ArkUI组件动画_arkui 小球动画

arkui 小球动画

一、ArkUI组件属性动画和显示动画

显示动画:

案例:上下左右箭头控制小鱼的游动  具体代码如下:

import router from '@ohos.router'

@Entry
@Component
struct AnimationPage {
  // 小鱼坐标
  @State fishX: number = 200
  @State fishY: number = 180
  // 小鱼角度
  @State angle: number = 0
  // 小鱼图片
  @State src: Resource = $r('app.media.fish')
  // 是否开始游戏
  @State isBegin: boolean = false

  build() {
    Row() {
      Stack() {
        // 返回按钮
        Button('返回')
          .position({ x: 0, y: 0 })
          .backgroundColor('#20101010')
          .onClick(() => {
            // 返回上一页
            router.back()
          })
        if (!this.isBegin) {
          // 开始游戏
          Button('开始游戏')
            .onClick(() => {
              // 点击后显示小鱼
              this.isBegin = true
            })
        } else {
          // 小鱼图片
          Image(this.src)
            .position({ x: this.fishX - 20, y: this.fishY - 20 }) // 中心点坐标
            .rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
            .width(40)
            .height(40)
          //.animation({duration: 500})

          // 操作按钮
          Row() {
            Button('⬅').backgroundColor('#20101010')
              .onClick(() => {
                // this.fishX -= 20
                // this.src = $r('app.media.fish_rev')
                // 显示动画
                animateTo({
                  duration: 500
                },
                  () => {
                    this.fishX -= 20
                    this.src = $r('app.media.fish_rev')
                  })
              })
            Column({ space: 40 }) {
              Button('⬆').backgroundColor('#20101010')
                .onClick(() => {
                  this.fishY -= 20
                })
              Button('⬇').backgroundColor('#20101010')
                .onClick(() => {
                  this.fishY += 20
                })
            }

            Button('➡').backgroundColor('#20101010')
              .onClick(() => {
                this.fishX += 20
                this.src = $r('app.media.fish')
              })
          }
          .width(240)
          .height(240)
        }
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
  }
}

二、ArkUI组件转场动画

代码如下:

import router from '@ohos.router'

@Entry
@Component
struct AnimationPage {
  // 小鱼坐标
  @State fishX: number = 200
  @State fishY: number = 180
  // 小鱼角度
  @State angle: number = 0
  // 小鱼图片
  @State src: Resource = $r('app.media.fish')
  // 是否开始游戏
  @State isBegin: boolean = false

  build() {
    Row() {
      Stack() {
        // 返回按钮
        Button('返回')
          .position({ x: 0, y: 0 })
          .backgroundColor('#20101010')
          .onClick(() => {
            // 返回上一页
            router.back()
          })
        if (!this.isBegin) {
          // 开始游戏
          Button('开始游戏')
            .onClick(() => {
              // 点击后显示小鱼
              // this.isBegin = true

              // 转场动画需结合animateTo才能生效
              animateTo({
                duration: 1000
              },
                () => {
                  // 点击后显示小鱼
                  this.isBegin = true
                })
            })
        } else {
          // 小鱼图片
          Image(this.src)
            .position({ x: this.fishX - 20, y: this.fishY - 20 }) // 中心点坐标
            .rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
            .width(40)
            .height(40)
              //.animation({duration: 500})
              // 添加转场动画
            .transition({
              // 开始游戏,入场动画
              type: TransitionType.Insert,
              opacity: 0, //一开始是透明的
              translate: { x: -250 }
            })
        }
        // 操作按钮
        Row() {
          Button('⬅').backgroundColor('#20101010')
            .onClick(() => {
              // this.fishX -= 20
              // this.src = $r('app.media.fish_rev')
              // 显示动画
              animateTo({
                duration: 500
              },
                () => {
                  this.fishX -= 20
                  this.src = $r('app.media.fish_rev')
                })
            })
          Column({ space: 40 }) {
            Button('⬆').backgroundColor('#20101010')
              .onClick(() => {
                this.fishY -= 20
              })
            Button('⬇').backgroundColor('#20101010')
              .onClick(() => {
                this.fishY += 20
              })
          }

          Button('➡').backgroundColor('#20101010')
            .onClick(() => {
              this.fishX += 20
              this.src = $r('app.media.fish')
            })
        }
        .width(240)
        .height(240)
        .justifyContent(FlexAlign.Center)
        .position({x: 0, y: 120})
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
  }
}

三、ArkUI组件实现摇杆功能

此功能自行开发

此块涉及到的主要是算法 ,比如三角函数

角度正弦和余弦

import router from '@ohos.router'
import { TouchEvent } from '@ohos.multimodalInput.touchEvent'
import curves from '@ohos.curves'

@Entry
@Component
struct AnimationPage {
  // 小鱼坐标
  @State fishX: number = 200
  @State fishY: number = 180
  // 小鱼角度
  @State angle: number = 0
  // 小鱼图片
  @State src: Resource = $r('app.media.fish')
  @State srcBg: Resource = $r('app.media.bg')
  // 是否开始游戏
  @State isBegin: boolean = false

  // 摇杆中心区域坐标
  private centerX: number = 120
  private centerY: number = 120

  // 大、小圆半径
  private maxRadius: number = 100
  private radius: number = 20

  // 摇杆小圆球初始位置
  @State positionX: number = this.centerX;
  @State positionY: number = this.centerY;

  // 角度正弦和余弦
  sin: number = 0
  cos: number = 0

  // 小鱼移动速度
  speed: number = 0

  // 任务id
  taskId: number = -1

  build() {
    Row() {
      Stack() {
        // 返回按钮
        Button('返回')
          .position({ x: 0, y: 0 })
          .backgroundColor('#20101010')
          .onClick(() => {
            // 返回上一页
            router.back()
          })
        if (!this.isBegin) {
          // 开始游戏
          Button('开始游戏')
            .onClick(() => {
              // 点击后显示小鱼
              // this.isBegin = true

              // 转场动画需结合animateTo才能生效
              animateTo({
                duration: 1000
              },
                () => {
                  // 点击后显示小鱼
                  this.isBegin = true
                })
            })
        } else {
          // 小鱼图片
          Image(this.src)
            .position({ x: this.fishX - 20, y: this.fishY - 20 }) // 中心点坐标
            .rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
            .width(40)
            .height(40)
              //.animation({duration: 500})
              // 添加转场动画
            .transition({
              // 开始游戏,入场动画
              type: TransitionType.Insert,
              opacity: 0, //一开始是透明的
              translate: { x: -250 }
            })
        }
        // 操作按钮
        Row() {
          Circle( {width: this.maxRadius * 2, height: this.maxRadius * 2})
            .fill('#20101010')
            .position({x: this.centerX - this.maxRadius, y: this.centerY - this.maxRadius})

          Circle( {width: this.radius * 2, height: this.radius * 2})
            .fill('#403A3A3A')
            .position({x: this.positionX - this.radius, y: this.positionY - this.radius})
        }
        .width(240)
        .height(240)
        .justifyContent(FlexAlign.Center)
        .position({x: 0, y: 120})
        .onTouch(this.handleTouchEvent.bind(this))
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundImage(this.srcBg)
  }

  // 处理手指移动的函数
  handleTouchEvent(event: TouchEvent) {
    // 1、先获取手指位置坐标
    // .x .y 我获取不到? 为啥
    let x = event.touches[0].screenX
    // @ts-ignore
    let y = event.touches[0].screenY
    // 2、计算手指与中心点的坐标差值
    let vx = x - this.centerX
    let vy = y - this.centerY
    // 3、计算手指与中心点连线和x轴正半轴的夹角,单位是弧度
    let angle = Math.atan2(vy, vx);
    // 4、计算手指与中心点的距离(角度正弦和余弦)
    let distance = this.getDistance(vx, vy)
    // 5、计算摇杆小球的坐标(x轴和y轴)
    this.sin = Math.sin(angle)
    this.cos = Math.cos(angle)
    animateTo({curve: curves.responsiveSpringMotion()},
      () => {
        this.positionX = this.centerX + (distance * this.sin)
        this.positionY = this.centerY + (distance * this.cos)
      })
  }

  getDistance(x: number, y: number) {
    let d = Math.sqrt(x * x + y * y)
    return Math.min(d, this.maxRadius)
  }
}

最终版:

import router from '@ohos.router'
import curves from '@ohos.curves'

@Entry
@Component
struct AnimationPage {
  // 小鱼坐标
  @State fishX: number = 200
  @State fishY: number = 180
  // 小鱼角度
  @State angle: number = 0
  // 小鱼图片
  @State src: Resource = $r('app.media.fish')
  @State srcBg: Resource = $r('app.media.bg')
  // 是否开始游戏
  @State isBegin: boolean = false

  // 摇杆中心区域坐标
  private centerX: number = 120
  private centerY: number = 120

  // 大、小圆半径
  private maxRadius: number = 100
  private radius: number = 20

  // 摇杆小圆球初始位置
  @State positionX: number = this.centerX;
  @State positionY: number = this.centerY;

  // 角度正弦和余弦
  sin: number = 0
  cos: number = 0

  // 小鱼移动速度
  speed: number = 0

  // 任务id
  taskId: number = -1

  build() {
    Row() {
      Stack() {
        // 返回按钮
        Button('返回')
          .position({ x: 0, y: 0 })
          .backgroundColor('#20101010')
          .onClick(() => {
            // 返回上一页
            router.back()
          })
        if (!this.isBegin) {
          // 开始游戏
          Button('开始游戏')
            .onClick(() => {
              // 点击后显示小鱼
              // this.isBegin = true

              // 转场动画需结合animateTo才能生效
              animateTo({
                duration: 1000
              },
                () => {
                  // 点击后显示小鱼
                  this.isBegin = true
                })
            })
        } else {
          // 小鱼图片
          Image(this.src)
            .position({ x: this.fishX - 20, y: this.fishY - 20 }) // 中心点坐标
            .rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
            .width(40)
            .height(40)
              //.animation({duration: 500})
              // 添加转场动画
            .transition({
              // 开始游戏,入场动画
              type: TransitionType.Insert,
              opacity: 0, //一开始是透明的
              translate: { x: -250 }
            })
        }
        // 操作按钮
        Row() {
          Circle( {width: this.maxRadius * 2, height: this.maxRadius * 2})
            .fill('#20101010')
            .position({x: this.centerX - this.maxRadius, y: this.centerY - this.maxRadius})

          Circle( {width: this.radius * 2, height: this.radius * 2})
            .fill('#403A3A3A')
            .position({x: this.positionX - this.radius, y: this.positionY - this.radius})
        }
        .width(240)
        .height(240)
        .justifyContent(FlexAlign.Center)
        .position({x: 0, y: 120})
        .onTouch(this.handleTouchEvent.bind(this))
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundImage(this.srcBg)
  }

  // 处理手指移动的函数
  handleTouchEvent(event: TouchEvent) {
    switch (event.type) {
      case TouchType.Up:
        // 还原小鱼的速度
        this.speed = 0
        // 取消定时任务
        clearInterval(this.taskId)
        // 还原摇杆小球的坐标 springMotion:还原动画
        animateTo({curve: curves.springMotion()},
          () => {
            this.positionX = this.centerX
            this.positionY = this.centerY
            this.angle = 0
          })
        break
      case TouchType.Down:
        // 开始定时任务
        this.taskId = setInterval(() => {
          this.fishX += this.speed * this.cos
          this.fishY += this.speed * this.sin
        }, 40);
        break
      case TouchType.Move:
        // 1、先获取手指位置坐标
        let x = event.touches[0].x
        let y = event.touches[0].y
        // 2、计算手指与中心点的坐标差值
        let vx = x - this.centerX
        let vy = y - this.centerY
        // 3、计算手指与中心点连线和x轴正半轴的夹角,单位是弧度
        let angle = Math.atan2(vy, vx);
        // 4、计算手指与中心点的距离(角度正弦和余弦)
        let distance = this.getDistance(vx, vy)
        this.sin = Math.sin(angle)
        this.cos = Math.cos(angle)
        // responsiveSpringMotion:跟手动画
        animateTo({curve: curves.responsiveSpringMotion()},
          () => {
            // 5、计算摇杆小球的坐标(x轴和y轴) 使用显示动画改变坐标
            this.positionX = this.centerX + (distance * this.sin)
            this.positionY = this.centerY + (distance * this.cos)

            // 6、修改小鱼的角度  [弧度转角度]
            if (Math.abs(angle * 2) < Math.PI) {
              // 判断弧度是否小于90度  正负90度 朝右游
              this.src = $r('app.media.fish')
            } else {
              this.src = $r('app.media.fish_rev')
              angle = angle < 0 ? angle + Math.PI : angle - Math.PI
            }
            this.angle = angle * 180 / Math.PI
            this.speed = 5
          })
        break
    }
  }

  getDistance(x: number, y: number) {
    let d = Math.sqrt(x * x + y * y)
    return Math.min(d, this.maxRadius)
  }
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/548362
推荐阅读
相关标签
  

闽ICP备14008679号