基于HarmonyOS ArkUI 3.0 框架的木棉花掃雷(上)
前言
HarmonyOS ArkUI 3.0 框架試玩初體驗二來了||ヽ( ̄▽ ̄)ノミ|Ю,這一次相比上一次的合成1024開發實戰,多了部分內容:顯示動畫、頁面跳轉與數據傳遞、網格容器Grid、自定義窗口等內容。本來想做成分布式HarmonyOS ArkUI 3.0木棉花掃雷的,但是苦于沒有相應API版本的分布式模擬器或多臺真機用于調試和運行,只能落得個單機的尷尬實戰了 ̄□ ̄||
效果圖

代碼文件結構

正文
一、創建一個空白的工程
1. 安裝和配置DevEco Studio 3.0
2. 創建一個Empty eTS Ability應用
DevEco Studio下載安裝成功后,打開DevEco Studio,點擊左上角的File,點擊New,再選擇New Project,選擇Empty Ability選項,點擊Next按鈕。

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

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

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

將entry>src>main>config.json文件中"js"項中的"pages"項中的"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文件中,通過Image($rawfile(‘LOGO.png’))可放置Logo圖片,通過Text(‘木棉花掃雷’)可放置文字內容。
屬性linearGradient為設置漸變顏色,linearGradient中的angle為漸變角度,設置為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. 添加動畫效果
這里使用的動畫效果是通過animateTo顯式動畫實現的。animateTo顯式動畫可以設置組件從狀態A到狀態B的變化動畫效果,包括樣式、位置信息和節點的增加刪除等,開發者無需關注變化過程,只需指定起點和終點的狀態。animateTo還提供播放狀態的回調接口,是對屬性動畫的增強與封裝。
添加狀態變量opacityValue和scaleValue并初始化為0,分別用于表示透明度和放縮的倍數,動畫效果中實現這兩個數值從0到1,即可實現Logo的漸出和放大效果。
定義一個貝塞爾曲線cubicBezier,Curves.cubicBezier(0.1, 0.2, 1, 1)。由于需要使用到動畫能力接口中的插值計算,故需要導入curves模塊。@ohos.curves模塊提供了線性Curve. Linear、階梯step、三階貝塞爾(cubicBezier)和彈簧(spring)插值曲線的初始化函數,可以根據入參創建一個插值曲線對象。
在animateTo顯式動畫中,設置動畫時長(duration)為2s,延時(delay)0.1s開始播放,設置顯示動效event的閉包函數(curve),即起點狀態到終點狀態為透明度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. 添加跳轉效果
先創建一個mainpage.ets文件。
在animateTo顯示動畫播放結束的onFinish回調接口中,調用定時器Timer的setTimeout接口延時1s后,調用router.replace,顯示mainpage.ets頁面。其中同樣需要導入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]]
- })
- }
- }
三、主頁頁面
1. 添加背景
游戲頁面的背景和歡迎頁面的背景幾乎一樣,這里就不重復啰嗦了。
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自定義按鈕。添加四個變量String、difficulty、Number_row和Number_column,分別用于記錄難度文本、地雷數量、網格的行數和網格的列數。在Button組件中設置圖片和文本的樣式。
在裝飾器@Entry裝飾的組件中,通過調用自定義組件的形式繪制三個按鈕。
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: '初級', difficulty: 10, Number_row: 9, Number_column: 9 });
- setButton({ String: '中級', difficulty: 30, Number_row: 12, Number_column: 12 });
- setButton({ String: '高級', 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() + '個')
- .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. 響應點擊跳轉事件
先創建一個game.ets文件。
在自定義按鈕組件中添加點擊事件onClick(),調用router.push接口,其中uri為跳轉的頁面,params為攜帶的數據,形式為params: { key: values },在新頁面調用router.getParams().key來獲取到頁面跳轉來時攜帶的key對應的數據,其中同樣需要導入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: '初級', difficulty: 10, Number_row: 9, Number_column: 9 });
- setButton({ String: '中級', difficulty: 30, Number_row: 12, Number_column: 12 });
- setButton({ String: '高級', 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() + '個')
- .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 }
- })
- })
- }
- }
至此,歡迎頁面和主頁面都已經全部完成了,在基于HarmonyOS ArkUI 3.0 框架的木棉花掃雷(下)將會繼續分享游戲頁面的實現(~ ̄▽ ̄)~
文章相關附件可以點擊下面的原文鏈接前往下載
https://harmonyos.51cto.com/resource/1541