在學(xué)習(xí)Harmonyos中實(shí)現(xiàn)了一個(gè)搖桿動(dòng)畫的效果,覺得很不錯(cuò),特來與諸位分享一下?。?!

image.png
搖桿實(shí)現(xiàn)
// 搖桿中心區(qū)域
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
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})
}
.height(240)
.width(240)
.justifyContent(FlexAlign.Center)
.position({x: 0, y: 120})
.onTouch(this.handleTouchEvent.bind(this))
// 處理手指移動(dòng)的事件
handleTouchEvent(event:TouchEvent) {
switch (event.type){
case TouchType.Up:
// 還原小魚速度
this.speed = 0
// 取消定時(shí)任務(wù)
clearInterval(this.taskId)
// 還原搖桿小球的坐標(biāo)
animateTo(
{curve: curves.springMotion()},
() => {
this.positionX = this.centerX
this.positionY = this.centerY
this.angle = 0
}
)
break
case TouchType.Down:
// 開始定時(shí)任務(wù)
this.taskId = setInterval(() => {
this.fishX += this.speed * this.cos
this.fishY += this.speed * this.sin
}, 40)
break
case TouchType.Move:
// 1. 獲取手指位置坐標(biāo)
let x = event.touches[0].x
let y = event.touches[0].y
// 2. 計(jì)算手指與中心點(diǎn)的坐標(biāo)差值
let vx = x - this.centerX
let vy = y - this.centerY
// 3. 計(jì)算手指與中心點(diǎn)連線和x正半軸的夾角,單位是弧度
let angle = Math.atan2(vy, vx)
// 4.計(jì)算手指與中心點(diǎn)的距離
let distance = this.getDistance(vx, vy)
this.sin = Math.sin(angle)
this.cos = Math.cos(angle)
animateTo(
{curve: curves.responsiveSpringMotion()},
() => {
// 5. 計(jì)算搖桿小球的坐標(biāo)
this.positionX = this.centerX + distance * this.cos
this.positionY = this.centerY + distance * this.sin
// 6. 修改小球的角度
if (Math.abs(angle * 2) < Math.PI) {
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)
}
代碼很簡(jiǎn)單,先是實(shí)現(xiàn)了兩個(gè)同心圓,根據(jù)已知的半徑,和位置就能實(shí)現(xiàn)兩個(gè)圓,在利用觸摸事件,實(shí)現(xiàn)搖桿的功能, getDistance 方法是獲取兩點(diǎn)之間的距離,利用反正切函數(shù)的vx和vy獲取距離,這就是核心代碼,與諸位共勉