基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)

系统 OpenHarmony
本来想做成分布式HarmonyOS ArkUI 3.0木棉花扫雷的,但是苦于没有相应API版本的分布式模拟器或多台真机用于调试和运行,只能落得个单机的尴尬实战了。

[[437923]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

HarmonyOS ArkUI 3.0 框架试玩初体验二来了||ヽ( ̄▽ ̄)ノミ|Ю,这一次相比上一次的合成1024开发实战,多了部分内容:显示动画、页面跳转与数据传递、网格容器Grid、自定义窗口等内容。本来想做成分布式HarmonyOS ArkUI 3.0木棉花扫雷的,但是苦于没有相应API版本的分布式模拟器或多台真机用于调试和运行,只能落得个单机的尴尬实战了 ̄□ ̄||

效果图

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

代码文件结构

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

正文

一、创建一个空白的工程

1. 安装和配置DevEco Studio 3.0

DevEco Studio 3.0下载

DevEco Studio 3.0安装

2. 创建一个Empty eTS Ability应用

DevEco Studio下载安装成功后,打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Empty Ability选项,点击Next按钮。

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

将文件命名为SaoLei(文件名不能出现中文或者特殊字符,否则将无法成功创建项目文件),Project Type勾选Application,选择保存路径,Language勾选eTS,选择API7,设备勾选Phone,最后点击Finish按钮。

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

3. 准备工作

在entry>src>main>config.json文件中最下方"launchType": "standard"的后面添加以下代码,这样就可以实现去掉应用上方的标签栏了。

config.json最下方部分代码:

  1. "metaData": { 
  2.       "customizeData": [ 
  3.         { 
  4.           "name""hwc-theme"
  5.           "value""androidhwext:style/Theme.Emui.Light.NoTitleBar"
  6.           "extra""" 
  7.         } 
  8.       ] 
  9.     } 

4. 保存图片

将图片保存到entry>src>main>resources>rawfile文件中。

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

二、欢迎页面

1. 更改文件名

在entry>src>ets>default>pages>index.ets文件右键,在弹出的菜单栏中选择Refactor,再在弹出的子菜单栏中选择Rename,或者按Shift+F6,将文件命名为logo.ets。

【木棉花】基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(上)-鸿蒙HarmonyOS技术社区

将entry>src>main>config.json文件中"js"项中的"pages"项中的"pages/index"更改为"pages/logo"。

config.json最下方部分代码:

  1. "js": [ 
  2.       { 
  3.         "mode": { 
  4.           "syntax""ets"
  5.           "type""pageAbility" 
  6.         }, 
  7.         "pages": [ 
  8.           "pages/logo" 
  9.         ], 
  10.         "name""default"
  11.         "window": { 
  12.           "designWidth": 720, 
  13.           "autoDesignWidth"false 
  14.         } 
  15.       } 
  16.     ] 

2. 添加背景

在logo.ets文件中,通过Image($rawfile(‘LOGO.png’))可放置Logo图片,通过Text(‘木棉花扫雷’)可放置文字内容。

属性linearGradient为设置渐变颜色,linearGradient中的angle为渐变角度,设置为180,即为从上往下渐变,colors则为渐变的颜色。

logo.ets:

  1. @Entry 
  2. @Component 
  3. struct Logo { 
  4.   build() { 
  5.     Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) { 
  6.       Image($rawfile('LOGO.png')) 
  7.         .objectFit(ImageFit.Contain) 
  8.         .height(300) 
  9.       Text('木棉花扫雷'
  10.         .fontSize(30) 
  11.         .fontColor(Color.White) 
  12.         .margin({ top: 200 }) 
  13.     } 
  14.     .width('100%'
  15.     .height('100%'
  16.     .linearGradient( 
  17.       { 
  18.         angle: 180, 
  19.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  20.       }) 
  21.   } 

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:

  1. // @ts-nocheck 
  2. import Curves from '@ohos.curves' 
  3.  
  4. @Entry 
  5. @Component 
  6. struct Logo { 
  7.   @State private opacityValue: number = 0 
  8.   @State private scaleValue: number = 0 
  9.   private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1) 
  10.  
  11.   build() { 
  12.     Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) { 
  13.       Image($rawfile('LOGO.png')) 
  14.         .objectFit(ImageFit.Contain) 
  15.         .height(300) 
  16.         .scale({ x: this.scaleValue, y: this.scaleValue }) 
  17.         .opacity(this.opacityValue) 
  18.         .onAppear(() => { 
  19.           animateTo({ 
  20.             duration: 2000, 
  21.             curve: this.curve1, 
  22.             delay: 100, 
  23.           }, () => { 
  24.             this.opacityValue = 1 
  25.             this.scaleValue = 1 
  26.           }) 
  27.         }) 
  28.       Text('木棉花扫雷'
  29.         .fontSize(30) 
  30.         .fontColor(Color.White) 
  31.         .margin({ top: 200 }) 
  32.     } 
  33.     .width('100%'
  34.     .height('100%'
  35.     .linearGradient( 
  36.       { 
  37.         angle: 180, 
  38.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  39.       }) 
  40.   } 

4. 添加跳转效果

先创建一个mainpage.ets文件。

在animateTo显示动画播放结束的onFinish回调接口中,调用定时器Timer的setTimeout接口延时1s后,调用router.replace,显示mainpage.ets页面。其中同样需要导入router模块。

logo.ets:

  1. // @ts-nocheck 
  2. import router from '@system.router' 
  3. import Curves from '@ohos.curves' 
  4.  
  5. @Entry 
  6. @Component 
  7. struct Logo { 
  8.   @State private opacityValue: number = 0 
  9.   @State private scaleValue: number = 0 
  10.   private curve1 = Curves.cubicBezier(0.1, 0.2, 1, 1) 
  11.  
  12.   build() { 
  13.     Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Column }) { 
  14.       Image($rawfile('LOGO.png')) 
  15.         .objectFit(ImageFit.Contain) 
  16.         .height(300) 
  17.         .scale({ x: this.scaleValue, y: this.scaleValue }) 
  18.         .opacity(this.opacityValue) 
  19.         .onAppear(() => { 
  20.           animateTo({ 
  21.             duration: 2000, 
  22.             curve: this.curve1, 
  23.             delay: 100, 
  24.             onFinish: () => { 
  25.               setTimeout(() => { 
  26.                 router.replace({ uri: "pages/mainpage" }) 
  27.               }, 1000); 
  28.             } 
  29.           }, () => { 
  30.             this.opacityValue = 1 
  31.             this.scaleValue = 1 
  32.           }) 
  33.         }) 
  34.       Text('木棉花扫雷'
  35.         .fontSize(30) 
  36.         .fontColor(Color.White) 
  37.         .margin({ top: 200 }) 
  38.     } 
  39.     .width('100%'
  40.     .height('100%'
  41.     .linearGradient( 
  42.       { 
  43.         angle: 180, 
  44.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  45.       }) 
  46.   } 

三、主页页面

1. 添加背景

游戏页面的背景和欢迎页面的背景几乎一样,这里就不重复啰嗦了。

mainpage.ets:

  1. @Entry 
  2. @Component 
  3. struct Mainpage { 
  4.   build() { 
  5.     Column() { 
  6.       Image($rawfile('mine.png')) 
  7.         .objectFit(ImageFit.Contain) 
  8.         .height(300) 
  9.         .scale({ x: 0.5, y: 0.5 }) 
  10.         .opacity(0.8) 
  11.     } 
  12.     .width('100%'
  13.     .height('100%'
  14.     .linearGradient( 
  15.       { 
  16.         angle: 180, 
  17.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  18.       }) 
  19.   } 

2. 添加按钮

从效果图可以看出按钮的样式是一致的,因此我们可以使用装饰器@Component自定义按钮。添加四个变量String、difficulty、Number_row和Number_column,分别用于记录难度文本、地雷数量、网格的行数和网格的列数。在Button组件中设置图片和文本的样式。

在装饰器@Entry装饰的组件中,通过调用自定义组件的形式绘制三个按钮。

mainpage.ets:

  1. @Entry 
  2. @Component 
  3. struct Mainpage { 
  4.   build() { 
  5.     Column() { 
  6.       Image($rawfile('mine.png')) 
  7.         .objectFit(ImageFit.Contain) 
  8.         .height(300) 
  9.         .scale({ x: 0.5, y: 0.5 }) 
  10.         .opacity(0.8) 
  11.  
  12.       setButton({ String: '初级', difficulty: 10, Number_row: 9, Number_column: 9 }); 
  13.       setButton({ String: '中级', difficulty: 30, Number_row: 12, Number_column: 12 }); 
  14.       setButton({ String: '高级', difficulty: 50, Number_row: 16, Number_column: 16 }); 
  15.     } 
  16.     .width('100%'
  17.     .height('100%'
  18.     .linearGradient( 
  19.       { 
  20.         angle: 180, 
  21.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  22.       }) 
  23.   } 
  24.  
  25. @Component 
  26. struct setButton { 
  27.   private String: string 
  28.   private difficulty: number 
  29.   private Number_row: number 
  30.   private Number_column: number 
  31.  
  32.   build() { 
  33.     Button({ type: ButtonType.Capsule, stateEffect: true }){ 
  34.       Column(){ 
  35.         Text(this.String) 
  36.           .textAlign(TextAlign.Center) 
  37.           .fontSize(30) 
  38.           .fontWeight(600) 
  39.           .fontColor('#0000FF'
  40.           .margin({ top: -5 }) 
  41.         Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) { 
  42.           Text('( ' + this.difficulty.toString() + '个'
  43.             .textAlign(TextAlign.Center) 
  44.             .fontSize(22) 
  45.             .fontWeight(600) 
  46.             .fontColor('#416EBE'
  47.             .margin({ top: -2, right: 5 }) 
  48.           Image($rawfile('mine.png')) 
  49.             .height(26) 
  50.             .width(26) 
  51.           Text(this.Number_row.toString() + '*' + this.Number_column.toString() + ' )'
  52.             .textAlign(TextAlign.Center) 
  53.             .fontSize(22) 
  54.             .fontWeight(600) 
  55.             .fontColor('#416EBE'
  56.             .margin({ left: 5, top: -2}) 
  57.         }.margin({ top: 5 }) 
  58.       } 
  59.     } 
  60.     .width(220) 
  61.     .height(90) 
  62.     .backgroundColor('#F3F7FF'
  63.     .margin({ top: 10 }) 
  64.   } 

3. 响应点击跳转事件

先创建一个game.ets文件。

在自定义按钮组件中添加点击事件onClick(),调用router.push接口,其中uri为跳转的页面,params为携带的数据,形式为params: { key: values },在新页面调用router.getParams().key来获取到页面跳转来时携带的key对应的数据,其中同样需要导入router模块。

mainpage.ets:

  1. import router from '@system.router' 
  2.  
  3. @Entry 
  4. @Component 
  5. struct Mainpage { 
  6.   build() { 
  7.     Column() { 
  8.       Image($rawfile('mine.png')) 
  9.         .objectFit(ImageFit.Contain) 
  10.         .height(300) 
  11.         .scale({ x: 0.5, y: 0.5 }) 
  12.         .opacity(0.8) 
  13.  
  14.       setButton({ String: '初级', difficulty: 10, Number_row: 9, Number_column: 9 }); 
  15.       setButton({ String: '中级', difficulty: 30, Number_row: 12, Number_column: 12 }); 
  16.       setButton({ String: '高级', difficulty: 50, Number_row: 16, Number_column: 16 }); 
  17.     } 
  18.     .width('100%'
  19.     .height('100%'
  20.     .linearGradient( 
  21.       { 
  22.         angle: 180, 
  23.         colors: [['#D3D7DC', 0.1], ["#B4BED2", 0.6],  ["#A0AAC8", 1]] 
  24.       }) 
  25.   } 
  26.  
  27. @Component 
  28. struct setButton { 
  29.   private String: string 
  30.   private difficulty: number 
  31.   private Number_row: number 
  32.   private Number_column: number 
  33.  
  34.   build() { 
  35.     Button({ type: ButtonType.Capsule, stateEffect: true }){ 
  36.       Column(){ 
  37.         Text(this.String) 
  38.           .textAlign(TextAlign.Center) 
  39.           .fontSize(30) 
  40.           .fontWeight(600) 
  41.           .fontColor('#0000FF'
  42.           .margin({ top: -5 }) 
  43.         Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, direction: FlexDirection.Row }) { 
  44.           Text('( ' + this.difficulty.toString() + '个'
  45.             .textAlign(TextAlign.Center) 
  46.             .fontSize(22) 
  47.             .fontWeight(600) 
  48.             .fontColor('#416EBE'
  49.             .margin({ top: -2, right: 5 }) 
  50.           Image($rawfile('mine.png')) 
  51.             .height(26) 
  52.             .width(26) 
  53.           Text(this.Number_row.toString() + '*' + this.Number_column.toString() + ' )'
  54.             .textAlign(TextAlign.Center) 
  55.             .fontSize(22) 
  56.             .fontWeight(600) 
  57.             .fontColor('#416EBE'
  58.             .margin({ left: 5, top: -2}) 
  59.         }.margin({ top: 5 }) 
  60.       } 
  61.     } 
  62.     .width(220) 
  63.     .height(90) 
  64.     .backgroundColor('#F3F7FF'
  65.     .margin({ top: 10 }) 
  66.     .onClick(() => { 
  67.       router.push({ 
  68.         uri: 'pages/game'
  69.         params: { difficulty: this.difficulty, Number_row: this.Number_row ,Number_column: this.Number_column } 
  70.       }) 
  71.     }) 
  72.   } 

 至此,欢迎页面和主页面都已经全部完成了,在基于HarmonyOS ArkUI 3.0 框架的木棉花扫雷(下)将会继续分享游戏页面的实现(~ ̄▽ ̄)~

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1541

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-12-01 15:40:23

鸿蒙HarmonyOS应用

2022-02-09 19:37:00

Ability鸿蒙开发

2021-11-02 14:52:17

鸿蒙HarmonyOS应用

2021-11-01 11:08:28

鸿蒙HarmonyOS应用

2021-09-17 14:47:33

鸿蒙HarmonyOS应用

2021-10-28 14:58:15

鸿蒙HarmonyOS应用

2022-11-02 16:06:54

ArkUIETS

2022-10-24 14:49:54

ArkUI心电图组件

2022-07-13 16:24:12

ArkUI(JS)打地鼠游戏

2022-09-21 14:51:21

ArkUI信件弹出

2022-06-27 14:12:32

css鸿蒙自定义

2021-11-02 14:55:42

鸿蒙HarmonyOS应用

2022-10-17 14:36:09

ArkUI虚拟摇杆组件

2022-09-14 15:17:26

ArkUI鸿蒙

2022-08-05 19:27:22

通用API鸿蒙

2024-01-11 15:54:55

eTS语言TypeScript应用开发

2022-03-17 15:28:18

五子棋HarmonyOSJSAPI

2021-12-27 15:10:55

鸿蒙HarmonyOS应用

2022-09-05 15:22:27

ArkUIets

2022-08-22 17:28:34

ArkUI鸿蒙
点赞
收藏

51CTO技术栈公众号