一、前言
近期我在學(xué)習(xí)鴻蒙應(yīng)用開(kāi)發(fā),跟著B(niǎo)站UP主黑馬程序員的視頻教程做了一個(gè)小魚(yú)動(dòng)畫(huà)應(yīng)用,UP主提供的小魚(yú)動(dòng)畫(huà)源代碼僅僅實(shí)現(xiàn)了移動(dòng)組件的功能,還存在一些問(wèn)題,如默認(rèn)進(jìn)入頁(yè)面是豎屏而頁(yè)面適合橫屏顯示;真機(jī)測(cè)試發(fā)現(xiàn)手機(jī)的狀態(tài)欄影響到了返回鍵對(duì)按鍵事件的響應(yīng);方向鍵不能響應(yīng)一直按著的操作;還有小魚(yú)會(huì)移出屏幕范圍。
之前已經(jīng)解決了強(qiáng)制橫屏和隱藏手機(jī)狀態(tài)欄,這次則是通過(guò)一番研究,實(shí)現(xiàn)了按鍵一直按下時(shí)控制小魚(yú)移動(dòng)和限制小魚(yú)移出屏幕這兩個(gè)功能。
?
二、實(shí)現(xiàn)方法
1. 一直按下方向鍵時(shí)控制小魚(yú)移動(dòng)
實(shí)現(xiàn)這一功能是在方向鍵下添加onTouch方法,對(duì)按鍵一直按下事件進(jìn)行響應(yīng)。在onTouch方法中還需要判斷TouchType.Down事件和TouchType.Up事件。在TouchType.Down事件時(shí),添加animateTo方法,實(shí)現(xiàn)按鍵時(shí)一直控制小魚(yú)移動(dòng)(需要通過(guò)setInterval方法設(shè)置定時(shí)任務(wù)讓animateTo方法定期執(zhí)行)。在TouchType.Up事件時(shí),通過(guò)clearInterval清除定時(shí)任務(wù),小魚(yú)就不會(huì)一直移動(dòng)了。以向右按鍵為例,改造后的代碼如下:
Button('→').backgroundColor('#20101010')
.onClick(() => {
animateTo(
{ duration: 500 },
() => {
this.src = $r('app.media.fish')
this.fishX += this.speed
}
)
})
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.taskId = setInterval(() => {
animateTo(
{ duration: 500 },
() => {
this.src = $r('app.media.fish')
this.fishX += this.speed
}
)
}, 200)
}
if (event.type === TouchType.Up) {
clearInterval(this.taskId)
this.taskId = -1
}
})
}
.height(240)
.width(240)
.justifyContent(FlexAlign.Center)
.position({ x: 0, y: 120 })
2.限制小魚(yú)移出屏幕
實(shí)現(xiàn)了上面的代碼后,一直按下方向鍵,小魚(yú)終于可以一直移動(dòng)了,但往一個(gè)方向一直移動(dòng)就會(huì)移出屏幕,為讓小魚(yú)不移出屏幕,還需要對(duì)按鍵操作事件進(jìn)行判斷,檢查當(dāng)前小魚(yú)的位置,只有小魚(yú)在限制的范圍內(nèi)才能執(zhí)行animateTo方法移動(dòng)小魚(yú)。
按下向左方向鍵:對(duì)小魚(yú)的X坐標(biāo)(this.fishX)進(jìn)行判斷。屏幕左側(cè)邊界的X值為0,小魚(yú)的大小為40(this.fishSize)。this.fishX是小魚(yú)圖片中心點(diǎn)的坐標(biāo),則當(dāng)小魚(yú)接觸到屏幕左側(cè)邊界時(shí),小魚(yú)的中心點(diǎn)X坐標(biāo)值為20。本軟件中設(shè)置的小魚(yú)的移動(dòng)速度為20(this.speed),因此,我設(shè)置的判斷條件是當(dāng)this.fishX >= this.fishSize時(shí),才能執(zhí)行animateTo方法。當(dāng)this.fishX == 40時(shí),再移動(dòng)一次this.fishX就變成了20,此時(shí)小魚(yú)圖片的左側(cè)邊緣正好接觸到屏幕左邊界。
按下向上方向鍵:對(duì)小魚(yú)的Y坐標(biāo)(this.fishY)進(jìn)行判斷。屏幕上邊界Y值為0,小魚(yú)大小為40。原理和按下向左方向機(jī)一樣。我設(shè)置的判斷條件是當(dāng)this.fishY >= this.fishSize時(shí),才能執(zhí)行animateTo方法。
對(duì)于屏幕下方的邊界和屏幕右側(cè)的邊界判斷需要導(dǎo)入模塊?import display from '@ohos.display' ,并在頁(yè)面的onPageShow方法獲取屏幕的尺寸信息。
onPageShow() {
// 獲取旋轉(zhuǎn)的方向,具體可以查看對(duì)應(yīng)文檔
let orientation = window.Orientation.LANDSCAPE;
// 獲取屏幕尺寸信息
let promise = display.getAllDisplays()
promise.then((data) => {
console.info('設(shè)備屏幕信息:' + JSON.stringify(data));
console.info('testTag', '屏幕寬度px:' + JSON.stringify(data[0].width));
console.info('testTag', '屏幕高度px:' + JSON.stringify(data[0].height));
this.screenWidth = px2vp(data[0].width)
this.screenHeight = px2vp(data[0].height)
console.info('testTag', '屏幕寬度vp:' + JSON.stringify(this.screenWidth));
console.info('testTag', '屏幕高度vp:' + JSON.stringify(this.screenHeight));
}).catch((err) => {
console.error('錯(cuò)誤信息:' + JSON.stringify(err));
})
}
按下向右方向機(jī):對(duì)小魚(yú)的X坐標(biāo)(this.fishX)進(jìn)行判斷。屏幕右側(cè)邊界的X值為變量this.screenHeight, 則判定語(yǔ)句為 this.fishX <= this.screenHeight - this.fishSize?。只有符合該條件是才執(zhí)行animateTo方法。
按下向下方向機(jī):對(duì)小魚(yú)的Y坐標(biāo)(this.fishY)進(jìn)行判斷。屏幕右側(cè)邊界的Y值為變量this.screenWidth, 則判定語(yǔ)句為 this.fishY <= this.screenWidth - this.fishSize?。只有符合該條件是才執(zhí)行animateTo方法。
這些判斷語(yǔ)句都要添加到方向鍵的onClick方法和onTouch方法。
三、完整源代碼
最后上這個(gè)文件的完整源代碼:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-791171.html
import router from '@ohos.router';
import window from '@ohos.window'; // 用于強(qiáng)制設(shè)為橫屏
import display from '@ohos.display'
@Entry
@Component
struct Aquarium1Page {
onPageShow() {
// 獲取旋轉(zhuǎn)的方向,具體可以查看對(duì)應(yīng)文檔
let orientation = window.Orientation.LANDSCAPE;
try {
// 設(shè)置屏幕旋轉(zhuǎn)
globalThis.windowClass.setPreferredOrientation(orientation, (err) => {
console.log('testTag', `onPageShow函數(shù)中setPreferredOrientation方法錯(cuò)誤碼為${err}`)
});
} catch (exception) {
console.error('設(shè)置失敗: ' + JSON.stringify(exception));
}
// 獲取屏幕尺寸信息
let promise = display.getAllDisplays()
promise.then((data) => {
console.info('設(shè)備屏幕信息:' + JSON.stringify(data));
console.info('testTag', '屏幕寬度px:' + JSON.stringify(data[0].width));
console.info('testTag', '屏幕高度px:' + JSON.stringify(data[0].height));
this.screenWidth = px2vp(data[0].width)
this.screenHeight = px2vp(data[0].height)
console.info('testTag', '屏幕寬度vp:' + JSON.stringify(this.screenWidth));
console.info('testTag', '屏幕高度vp:' + JSON.stringify(this.screenHeight));
}).catch((err) => {
console.error('錯(cuò)誤信息:' + JSON.stringify(err));
})
}
onPageHide() {
// 獲取旋轉(zhuǎn)的方向,具體可以查看對(duì)應(yīng)文檔
let orientation = window.Orientation.PORTRAIT;
try {
// 設(shè)置屏幕旋轉(zhuǎn)
globalThis.windowClass.setPreferredOrientation(orientation, (err) => {
console.log('testTag', `onPageHide函數(shù)中setPreferredOrientation方法錯(cuò)誤碼為${err}`)
});
} catch (exception) {
console.error('設(shè)置失敗: ' + JSON.stringify(exception));
}
}
// 小魚(yú)的位置
@State fishX: number = 200
@State fishY: number = 180
// 小魚(yú)的大小
fishSize: number = 40
// 小魚(yú)角度
@State angle: number = 0
// 小魚(yú)圖片
@State src: Resource = $r('app.media.fish')
// 是否開(kāi)始游戲
@State isBegin: boolean = false
// 小魚(yú)的速度
speed: number = 20
// 用于控制Interval的id
taskId: number = -1
// 屏幕尺寸
screenWidth: number = px2vp(2000)
screenHeight: number = px2vp(1080)
build() {
Row() {
Stack() {
Button('返回')
.position({ x: 20, y: 20 })
.backgroundColor('#20101010')
.onClick(() => {
router.back()
})
if (!this.isBegin) {
Button('開(kāi)始游戲')
.onClick(() => {
animateTo(
{ duration: 1000 },
() => {
// 點(diǎn)擊后顯示小魚(yú)
this.isBegin = true
}
)
})
} else {
// 小魚(yú)圖片
Image(this.src)
.position({ x: this.fishX - 20, y: this.fishY - 20 })
.rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
.width(this.fishSize)
.height(this.fishSize)
//.animation({duration: 500, curve: Curve.Smooth})
.transition({
type: TransitionType.Insert,
opacity: 0,
translate: { x: -250 }
})
}
// 操作按鈕
Row() {
// 向左移動(dòng),小魚(yú)身體不能超出屏幕范圍
Button('←').backgroundColor('#20101010')
.onClick(() => {
if (this.fishX >= this.fishSize) {
animateTo(
{ duration: 500 },
() => {
this.src = $r('app.media.fish_rev')
this.fishX -= this.speed
}
)
}
})
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.taskId = setInterval(() => {
animateTo(
{ duration: 500 },
() => {
if (this.fishX >= this.fishSize) {
this.src = $r('app.media.fish_rev')
this.fishX -= this.speed
}
}
)
}, 200)
}
if (event.type === TouchType.Up) {
clearInterval(this.taskId)
this.taskId = -1
}
})
Column({ space: 40 }) {
// 向上和向下移動(dòng),小魚(yú)的身體均不能超出屏幕范圍
Button('↑').backgroundColor('#20101010')
.onClick(() => {
if (this.fishY >= this.fishSize) {
animateTo(
{ duration: 500 },
() => {
this.fishY -= this.speed
}
)
}
})
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.taskId = setInterval(() => {
animateTo(
{ duration: 500 },
() => {
if (this.fishY >= this.fishSize) {
this.fishY -= this.speed
}
}
)
}, 200)
}
if (event.type === TouchType.Up) {
console.log("testTag", `停止向上,當(dāng)前fishY為:${this.fishY}`)
clearInterval(this.taskId)
this.taskId = -1
}
})
Button('↓').backgroundColor('#20101010')
.onClick(() => {
if (this.fishY <= this.screenWidth - this.fishSize) {
animateTo(
{ duration: 500 },
() => {
this.fishY += this.speed
}
)
}
})
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.taskId = setInterval(() => {
animateTo(
{ duration: 500 },
() => {
if (this.fishY <= this.screenWidth - this.fishSize) {
this.fishY += this.speed
}
}
)
}, 200)
}
if (event.type === TouchType.Up) {
console.log("testTag", `停止向下,當(dāng)前fishY為:${this.fishY}`)
clearInterval(this.taskId)
this.taskId = -1
}
})
}
Button('→').backgroundColor('#20101010')
.onClick(() => {
if (this.fishX <= this.screenHeight - this.fishSize) {
animateTo(
{ duration: 500 },
() => {
this.src = $r('app.media.fish')
this.fishX += this.speed
}
)
}
})
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.taskId = setInterval(() => {
animateTo(
{ duration: 500 },
() => {
if (this.fishX <= this.screenHeight - this.fishSize) {
this.src = $r('app.media.fish')
this.fishX += this.speed
}
}
)
}, 200)
}
if (event.type === TouchType.Up) {
clearInterval(this.taskId)
this.taskId = -1
}
})
}
.height(240)
.width(240)
.justifyContent(FlexAlign.Center)
.position({ x: 0, y: 120 })
}
.height('100%').width('100%')
}
.width('100%')
.height('100%')
.backgroundImage($r('app.media.underwater_cartoon'))
.backgroundImageSize({ height: '100%', width: '100%' })
}
}
四、B站視頻鏈接:
鴻蒙應(yīng)用開(kāi)發(fā)學(xué)習(xí):改進(jìn)小魚(yú)動(dòng)畫(huà)實(shí)現(xiàn)按鍵一直按下時(shí)控制小魚(yú)移動(dòng)和限制小魚(yú)移出屏幕-CSDN博客文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-791171.html
到了這里,關(guān)于鴻蒙應(yīng)用開(kāi)發(fā)學(xué)習(xí):改進(jìn)小魚(yú)動(dòng)畫(huà)實(shí)現(xiàn)按鍵一直按下時(shí)控制小魚(yú)移動(dòng)和限制小魚(yú)移出屏幕的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!