基于HarmonyOS ArkUI 3.0 框架的木棉花掃雷(上)
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
HarmonyOS ArkUI 3.0 框架試玩初體驗(yàn)二來(lái)了||ヽ( ̄▽ ̄)ノミ|Ю,這一次相比上一次的合成1024開(kāi)發(fā)實(shí)戰(zhàn),多了部分內(nèi)容:顯示動(dòng)畫、頁(yè)面跳轉(zhuǎn)與數(shù)據(jù)傳遞、網(wǎng)格容器Grid、自定義窗口等內(nèi)容。本來(lái)想做成分布式HarmonyOS ArkUI 3.0木棉花掃雷的,但是苦于沒(méi)有相應(yīng)API版本的分布式模擬器或多臺(tái)真機(jī)用于調(diào)試和運(yùn)行,只能落得個(gè)單機(jī)的尷尬實(shí)戰(zhàn)了 ̄□ ̄||
效果圖

代碼文件結(jié)構(gòu)

正文
一、創(chuàng)建一個(gè)空白的工程
1. 安裝和配置DevEco Studio 3.0
2. 創(chuàng)建一個(gè)Empty eTS Ability應(yīng)用
DevEco Studio下載安裝成功后,打開(kāi)DevEco Studio,點(diǎn)擊左上角的File,點(diǎn)擊New,再選擇New Project,選擇Empty Ability選項(xiàng),點(diǎn)擊Next按鈕。

將文件命名為SaoLei(文件名不能出現(xiàn)中文或者特殊字符,否則將無(wú)法成功創(chuàng)建項(xiàng)目文件),Project Type勾選Application,選擇保存路徑,Language勾選eTS,選擇API7,設(shè)備勾選Phone,最后點(diǎn)擊Finish按鈕。

3. 準(zhǔn)備工作
在entry>src>main>config.json文件中最下方"launchType": "standard"的后面添加以下代碼,這樣就可以實(shí)現(xiàn)去掉應(yīng)用上方的標(biāo)簽欄了。
config.json最下方部分代碼:
- "metaData": {
- "customizeData": [
- {
- "name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar",
- "extra": ""
- }
- ]
- }
4. 保存圖片
將圖片保存到entry>src>main>resources>rawfile文件中。

二、歡迎頁(yè)面
1. 更改文件名
在entry>src>ets>default>pages>index.ets文件右鍵,在彈出的菜單欄中選擇Refactor,再在彈出的子菜單欄中選擇Rename,或者按Shift+F6,將文件命名為logo.ets。

將entry>src>main>config.json文件中"js"項(xiàng)中的"pages"項(xiàng)中的"pages/index"更改為"pages/logo"。
config.json最下方部分代碼:
- "js": [
- {
- "mode": {
- "syntax": "ets",
- "type": "pageAbility"
- },
- "pages": [
- "pages/logo"
- ],
- "name": "default",
- "window": {
- "designWidth": 720,
- "autoDesignWidth": false
- }
- }
- ]
2. 添加背景
在logo.ets文件中,通過(guò)Image($rawfile(‘LOGO.png’))可放置Logo圖片,通過(guò)Text(‘木棉花掃雷’)可放置文字內(nèi)容。
屬性linearGradient為設(shè)置漸變顏色,linearGradient中的angle為漸變角度,設(shè)置為180,即為從上往下漸變,colors則為漸變的顏色。
logo.ets:
- @Entry
- @Component
- struct Logo {
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Image($rawfile('LOGO.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- Text('木棉花掃雷')
- .fontSize(30)
- .fontColor(Color.White)
- .margin({ top: 200 })
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
3. 添加動(dòng)畫效果
這里使用的動(dòng)畫效果是通過(guò)animateTo顯式動(dòng)畫實(shí)現(xiàn)的。animateTo顯式動(dòng)畫可以設(shè)置組件從狀態(tài)A到狀態(tài)B的變化動(dòng)畫效果,包括樣式、位置信息和節(jié)點(diǎn)的增加刪除等,開(kāi)發(fā)者無(wú)需關(guān)注變化過(guò)程,只需指定起點(diǎn)和終點(diǎn)的狀態(tài)。animateTo還提供播放狀態(tài)的回調(diào)接口,是對(duì)屬性動(dòng)畫的增強(qiáng)與封裝。
添加狀態(tài)變量opacityValue和scaleValue并初始化為0,分別用于表示透明度和放縮的倍數(shù),動(dòng)畫效果中實(shí)現(xiàn)這兩個(gè)數(shù)值從0到1,即可實(shí)現(xiàn)Logo的漸出和放大效果。
定義一個(gè)貝塞爾曲線cubicBezier,Curves.cubicBezier(0.1, 0.2, 1, 1)。由于需要使用到動(dòng)畫能力接口中的插值計(jì)算,故需要導(dǎo)入curves模塊。@ohos.curves模塊提供了線性Curve. Linear、階梯step、三階貝塞爾(cubicBezier)和彈簧(spring)插值曲線的初始化函數(shù),可以根據(jù)入?yún)?chuàng)建一個(gè)插值曲線對(duì)象。
在animateTo顯式動(dòng)畫中,設(shè)置動(dòng)畫時(shí)長(zhǎng)(duration)為2s,延時(shí)(delay)0.1s開(kāi)始播放,設(shè)置顯示動(dòng)效event的閉包函數(shù)(curve),即起點(diǎn)狀態(tài)到終點(diǎn)狀態(tài)為透明度opacityValue和大小scaleValue從0到1。
logo.ets:
- // @ts-nocheck
- import Curves from '@ohos.curves'
- @Entry
- @Component
- struct Logo {
- @State private opacityValue: number = 0
- @State private scaleValue: number = 0
- private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1)
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Image($rawfile('LOGO.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- .scale({ x: this.scaleValue, y: this.scaleValue })
- .opacity(this.opacityValue)
- .onAppear(() => {
- animateTo({
- duration: 2000,
- curve: this.curve1,
- delay: 100,
- }, () => {
- this.opacityValue = 1
- this.scaleValue = 1
- })
- })
- Text('木棉花掃雷')
- .fontSize(30)
- .fontColor(Color.White)
- .margin({ top: 200 })
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
4. 添加跳轉(zhuǎn)效果
先創(chuàng)建一個(gè)mainpage.ets文件。
在animateTo顯示動(dòng)畫播放結(jié)束的onFinish回調(diào)接口中,調(diào)用定時(shí)器Timer的setTimeout接口延時(shí)1s后,調(diào)用router.replace,顯示mainpage.ets頁(yè)面。其中同樣需要導(dǎo)入router模塊。
logo.ets:
- // @ts-nocheck
- import router from '@system.router'
- import Curves from '@ohos.curves'
- @Entry
- @Component
- struct Logo {
- @State private opacityValue: number = 0
- @State private scaleValue: number = 0
- private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1)
- build() {
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) {
- Image($rawfile('LOGO.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- .scale({ x: this.scaleValue, y: this.scaleValue })
- .opacity(this.opacityValue)
- .onAppear(() => {
- animateTo({
- duration: 2000,
- curve: this.curve1,
- delay: 100,
- onFinish: () => {
- setTimeout(() => {
- router.replace({ uri: "pages/mainpage" })
- }, 1000);
- }
- }, () => {
- this.opacityValue = 1
- this.scaleValue = 1
- })
- })
- Text('木棉花掃雷')
- .fontSize(30)
- .fontColor(Color.White)
- .margin({ top: 200 })
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
三、主頁(yè)頁(yè)面
1. 添加背景
游戲頁(yè)面的背景和歡迎頁(yè)面的背景幾乎一樣,這里就不重復(fù)啰嗦了。
mainpage.ets:
- @Entry
- @Component
- struct Mainpage {
- build() {
- Column() {
- Image($rawfile('mine.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- .scale({ x: 0.5, y: 0.5 })
- .opacity(0.8)
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
2. 添加按鈕
從效果圖可以看出按鈕的樣式是一致的,因此我們可以使用裝飾器@Component自定義按鈕。添加四個(gè)變量String、difficulty、Number_row和Number_column,分別用于記錄難度文本、地雷數(shù)量、網(wǎng)格的行數(shù)和網(wǎng)格的列數(shù)。在Button組件中設(shè)置圖片和文本的樣式。
在裝飾器@Entry裝飾的組件中,通過(guò)調(diào)用自定義組件的形式繪制三個(gè)按鈕。
mainpage.ets:
- @Entry
- @Component
- struct Mainpage {
- build() {
- Column() {
- Image($rawfile('mine.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- .scale({ x: 0.5, y: 0.5 })
- .opacity(0.8)
- setButton({ String: '初級(jí)', difficulty: 10, Number_row: 9, Number_column: 9 });
- setButton({ String: '中級(jí)', difficulty: 30, Number_row: 12, Number_column: 12 });
- setButton({ String: '高級(jí)', difficulty: 50, Number_row: 16, Number_column: 16 });
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
- @Component
- struct setButton {
- private String: string
- private difficulty: number
- private Number_row: number
- private Number_column: number
- build() {
- Button({ type: ButtonType.Capsule, stateEffect: true }){
- Column(){
- Text(this.String)
- .textAlign(TextAlign.Center)
- .fontSize(30)
- .fontWeight(600)
- .fontColor('#0000FF')
- .margin({ top: -5 })
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
- Text('( ' + this.difficulty.toString() + '個(gè)')
- .textAlign(TextAlign.Center)
- .fontSize(22)
- .fontWeight(600)
- .fontColor('#416EBE')
- .margin({ top: -2, right: 5 })
- Image($rawfile('mine.png'))
- .height(26)
- .width(26)
- Text(this.Number_row.toString() + '*' + this.Number_column.toString() + ' )')
- .textAlign(TextAlign.Center)
- .fontSize(22)
- .fontWeight(600)
- .fontColor('#416EBE')
- .margin({ left: 5, top: -2})
- }.margin({ top: 5 })
- }
- }
- .width(220)
- .height(90)
- .backgroundColor('#F3F7FF')
- .margin({ top: 10 })
- }
- }
3. 響應(yīng)點(diǎn)擊跳轉(zhuǎn)事件
先創(chuàng)建一個(gè)game.ets文件。
在自定義按鈕組件中添加點(diǎn)擊事件onClick(),調(diào)用router.push接口,其中uri為跳轉(zhuǎn)的頁(yè)面,params為攜帶的數(shù)據(jù),形式為params: { key: values },在新頁(yè)面調(diào)用router.getParams().key來(lái)獲取到頁(yè)面跳轉(zhuǎn)來(lái)時(shí)攜帶的key對(duì)應(yīng)的數(shù)據(jù),其中同樣需要導(dǎo)入router模塊。
mainpage.ets:
- import router from '@system.router'
- @Entry
- @Component
- struct Mainpage {
- build() {
- Column() {
- Image($rawfile('mine.png'))
- .objectFit(ImageFit.Contain)
- .height(300)
- .scale({ x: 0.5, y: 0.5 })
- .opacity(0.8)
- setButton({ String: '初級(jí)', difficulty: 10, Number_row: 9, Number_column: 9 });
- setButton({ String: '中級(jí)', difficulty: 30, Number_row: 12, Number_column: 12 });
- setButton({ String: '高級(jí)', difficulty: 50, Number_row: 16, Number_column: 16 });
- }
- .width('100%')
- .height('100%')
- .linearGradient(
- {
- angle: 180,
- colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6], ["#A0AAC8", 1]]
- })
- }
- }
- @Component
- struct setButton {
- private String: string
- private difficulty: number
- private Number_row: number
- private Number_column: number
- build() {
- Button({ type: ButtonType.Capsule, stateEffect: true }){
- Column(){
- Text(this.String)
- .textAlign(TextAlign.Center)
- .fontSize(30)
- .fontWeight(600)
- .fontColor('#0000FF')
- .margin({ top: -5 })
- Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) {
- Text('( ' + this.difficulty.toString() + '個(gè)')
- .textAlign(TextAlign.Center)
- .fontSize(22)
- .fontWeight(600)
- .fontColor('#416EBE')
- .margin({ top: -2, right: 5 })
- Image($rawfile('mine.png'))
- .height(26)
- .width(26)
- Text(this.Number_row.toString() + '*' + this.Number_column.toString() + ' )')
- .textAlign(TextAlign.Center)
- .fontSize(22)
- .fontWeight(600)
- .fontColor('#416EBE')
- .margin({ left: 5, top: -2})
- }.margin({ top: 5 })
- }
- }
- .width(220)
- .height(90)
- .backgroundColor('#F3F7FF')
- .margin({ top: 10 })
- .onClick(() => {
- router.push({
- uri: 'pages/game',
- params: { difficulty: this.difficulty, Number_row: this.Number_row ,Number_column: this.Number_column }
- })
- })
- }
- }
至此,歡迎頁(yè)面和主頁(yè)面都已經(jīng)全部完成了,在基于HarmonyOS ArkUI 3.0 框架的木棉花掃雷(下)將會(huì)繼續(xù)分享游戲頁(yè)面的實(shí)現(xiàn)(~ ̄▽ ̄)~
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載
https://harmonyos.51cto.com/resource/1541
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)