鸿蒙NEXT开发案例:抛硬币

news/2024/11/12 18:48:00/文章来源:https://www.cnblogs.com/zhongcx/p/18538856

 

【1】引言(完整代码在最后面)

本项目旨在实现一个简单的“抛硬币”功能,用户可以通过点击屏幕上的地鼠图标来模拟抛硬币的过程。应用会记录并显示硬币正面(地鼠面)和反面(数字100面)出现的次数。为了增强用户体验,我们还添加了动画效果,使抛硬币的过程更加生动有趣。

【2】环境准备

电脑系统:windows 10

开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

工程版本:API 12

真机:mate60 pro

语言:ArkTS、ArkUI

【3】应用结构

应用主要由两个部分组成:地鼠组件(Hamster)和主页面组件(CoinTossPage)。

地鼠组件(Hamster)

地鼠组件是应用的核心视觉元素之一,负责展示地鼠的形象。该组件通过@Component装饰器定义,并接收一个属性cellWidth,用于控制组件的大小。

主页面组件(CoinTossPage)

主页面组件是整个应用的入口点,负责组织和管理各个UI元素。该组件同样通过@Component装饰器定义,并包含多个状态变量用于跟踪硬币的状态和动画进度。

【4】功能解析

1. 地鼠组件:

• 通过Stack布局组合多个图形元素,创建了一个地鼠的形象。

• 每个图形元素都设置了具体的尺寸、颜色、边框等样式,并通过margin属性调整位置。

2. 主页面组件:

• 顶部有一个“抛硬币”的标题,下方是一个行布局,用于展示地鼠组件及正反两面出现的次数。

• 地鼠组件被放置在一个圆形区域内,背景采用线性渐变色。

• 点击地鼠时,会触发一系列动画效果,模拟硬币抛起再落下的过程。

• 通过计算最终的角度,判断是正面还是反面朝上,并更新相应的计数。

【完整代码】

// 定义地鼠组件
@Component
struct Hamster {@Prop cellWidth: number // 单元格宽度build() {Stack() { // 创建一个堆叠布局// 身体Text().width(`${this.cellWidth / 2}lpx`)// 宽度为单元格宽度的一半.height(`${this.cellWidth / 3 * 2}lpx`)// 高度为单元格高度的2/3.backgroundColor("#b49579")// 背景颜色.borderRadius({ topLeft: '50%', topRight: '50%' })// 圆角.borderColor("#2a272d")// 边框颜色.borderWidth(1) // 边框宽度// 嘴巴Ellipse().width(`${this.cellWidth / 4}lpx`)// 嘴巴的宽度.height(`${this.cellWidth / 5}lpx`)// 嘴巴的高度.fillOpacity(1)// 填充不透明度.fill("#e7bad7")// 填充颜色.stroke("#563e3f")// 边框颜色.strokeWidth(1)// 边框宽度.margin({ top: `${this.cellWidth / 6}lpx` }) // 上边距// 左眼睛Ellipse().width(`${this.cellWidth / 9}lpx`)// 左眼睛的宽度.height(`${this.cellWidth / 6}lpx`)// 左眼睛的高度.fillOpacity(1)// 填充不透明度.fill("#313028")// 填充颜色.stroke("#2e2018")// 边框颜色.strokeWidth(1)// 边框宽度.margin({ bottom: `${this.cellWidth / 3}lpx`, right: `${this.cellWidth / 6}lpx` }) // 下边距和右边距// 右眼睛Ellipse().width(`${this.cellWidth / 9}lpx`)// 右眼睛的宽度.height(`${this.cellWidth / 6}lpx`)// 右眼睛的高度.fillOpacity(1)// 填充不透明度.fill("#313028")// 填充颜色.stroke("#2e2018")// 边框颜色.strokeWidth(1)// 边框宽度.margin({ bottom: `${this.cellWidth / 3}lpx`, left: `${this.cellWidth / 6}lpx` }) // 下边距和左边距// 左眼瞳Ellipse().width(`${this.cellWidth / 20}lpx`)// 左眼瞳的宽度.height(`${this.cellWidth / 15}lpx`)// 左眼瞳的高度.fillOpacity(1)// 填充不透明度.fill("#fefbfa")// 填充颜色.margin({ bottom: `${this.cellWidth / 2.5}lpx`, right: `${this.cellWidth / 6}lpx` }) // 下边距和右边距// 右眼瞳Ellipse().width(`${this.cellWidth / 20}lpx`)// 右眼瞳的宽度.height(`${this.cellWidth / 15}lpx`)// 右眼瞳的高度.fillOpacity(1)// 填充不透明度.fill("#fefbfa")// 填充颜色.margin({ bottom: `${this.cellWidth / 2.5}lpx`, left: `${this.cellWidth / 6}lpx` }) // 下边距和左边距}.width(`${this.cellWidth}lpx`).height(`${this.cellWidth}lpx`) // 设置组件的宽度和高度}
}// 定义页面组件
@Entry
@Component
struct CoinTossPage {@State cellWidth: number = 50 // 单元格宽度@State headsCount: number = 0 // 正面朝上的次数@State tailsCount: number = 0 // 反面朝上的次数@State rotationAngle: number = 0 // 旋转角度@State verticalOffset: number = 0 // 纵向位移@State isAnimRun: boolean = false // 动画是否正在执行build() {Column() {// 页面标题Text('抛硬币').height(50)// 高度设置为50.width('100%')// 宽度设置为100%.textAlign(TextAlign.Center)// 文本居中对齐.fontColor("#fefefe")// 字体颜色.fontSize(20); // 字体大小// 显示地鼠和计数Row({ space: 20 }) {Stack() {Hamster({ cellWidth: this.cellWidth }) // 创建地鼠组件}.borderRadius('50%') // 设置圆角.width(`${this.cellWidth}lpx`) // 设置宽度.height(`${this.cellWidth}lpx`) // 设置高度.linearGradient({// 设置线性渐变背景direction: GradientDirection.LeftBottom,colors: [['#ebcf2f', 0.0], ['#fef888', 0.5], ['#ebcf2f', 1.0]]});// 显示反面朝上的次数Text(`${this.tailsCount}`).fontSize(20).fontColor("#fefefe");Stack() {// 显示100Text("100").fontColor("#9f7606").fontSize(`${this.cellWidth / 2}lpx`);}.borderRadius('50%') // 设置圆角.width(`${this.cellWidth}lpx`) // 设置宽度.height(`${this.cellWidth}lpx`) // 设置高度.linearGradient({// 设置线性渐变背景direction: GradientDirection.LeftBottom,colors: [['#ebcf2f', 0.0], ['#fef888', 0.5], ['#ebcf2f', 1.0]]});// 显示正面朝上的次数Text(`${this.headsCount}`).fontSize(20).fontColor("#fefefe");}.width('100%').justifyContent(FlexAlign.Center); // 设置宽度和内容居中对齐Stack() {Stack() {// 创建放大版地鼠组件Hamster({ cellWidth: this.cellWidth * 3 }).visibility(this.isHeadsFaceUp() ? Visibility.Visible : Visibility.Hidden); // 根据状态显示或隐藏// 显示100Text("100").fontColor("#9f7606")// 字体颜色.fontSize(`${this.cellWidth / 2 * 3}lpx`)// 字体大小.visibility(!this.isHeadsFaceUp() ? Visibility.Visible : Visibility.Hidden)// 根据状态显示或隐藏.rotate({// 旋转180度x: 1,y: 0,z: 0,angle: 180});}.borderRadius('50%') // 设置圆角.width(`${this.cellWidth * 3}lpx`) // 设置宽度.height(`${this.cellWidth * 3}lpx`) // 设置高度.linearGradient({// 设置线性渐变背景direction: GradientDirection.LeftBottom,colors: [['#ebcf2f', 0.0], ['#fef888', 0.5], ['#ebcf2f', 1.0]]}).rotate({// 根据当前角度旋转x: 1,y: 0,z: 0,angle: this.rotationAngle}).translate({ x: 0, y: this.verticalOffset }) // 设置纵向位移.onClick(() => { // 点击事件处理if (this.isAnimRun) {return;}this.isAnimRun = truelet maxAnimationSteps = 2 * (10 + Math.floor(Math.random() * 10)); // 计算最大动画次数let totalAnimationDuration = 2000; // 动画总时长// 第一次动画,向上抛出animateToImmediately({duration: totalAnimationDuration / 2, // 动画时长为总时长的一半onFinish: () => { // 动画完成后的回调// 第二次动画,向下落animateToImmediately({duration: totalAnimationDuration / 2,onFinish: () => {this.rotationAngle = this.rotationAngle % 360; // 确保角度在0到360之间// 判断当前显示的面if (this.isHeadsFaceUp()) { // 如果是地鼠面this.tailsCount++; // 反面朝上的次数加1} else { // 如果是反面this.headsCount++; // 正面朝上的次数加1}this.isAnimRun = false}}, () => {this.verticalOffset = 0; // 重置纵向位移});}}, () => {// 设置纵向位移,模拟抛硬币的效果this.verticalOffset = -100 * (1 + Math.floor(Math.random() * 5)); // 随机设置向上的位移});// 循环动画,增加旋转效果for (let i = 0; i < maxAnimationSteps; i++) {animateToImmediately({delay: i * totalAnimationDuration / maxAnimationSteps, // 设置每次动画的延迟duration: 100, // 每次动画的持续时间onFinish: () => {// 动画完成后的回调}}, () => {this.rotationAngle += 90; // 每次增加90度旋转});}});}.width('100%').layoutWeight(1).align(Alignment.Bottom).padding({ bottom: 80 }); // 设置组件的宽度、权重、对齐方式和底部内边距}.height('100%') // 设置整个页面的高度.width('100%') // 设置整个页面的宽度.backgroundColor("#0b0d0c"); // 设置背景颜色}// 判断当前是否显示地鼠面isHeadsFaceUp() {let normalizedAngle = this.rotationAngle % 360; // 规范化角度// 判断角度范围,确定是否显示地鼠面if (normalizedAngle >= 0 && normalizedAngle < 90 || normalizedAngle >= 270 && normalizedAngle <= 360) {return true; // 显示地鼠面}return false; // 显示反面}
}

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/831154.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CodeForces训练记录】Codeforces Round 986 (Div. 2)

训练情况赛后反思 C题逆风翻盘,可能勉强青名了。A题愣神了,我觉得还能再做的快一点。 A题 给定一个字符串,NWSE,重复着字符串走,我们直接模拟即可,用 while 来判断是否走到终点,然后对于不可能走到的终点,我选择了一个不会超时的步数范围,超出就跳出 while 即可,最后…

24. 使用MySQL之使用游标

1. 游标 由前几章可知,MySQL检索操作返回一组称为结果集的行。这组返回的行都是与SQL语句相匹配的行(零行或多行)。 使用简单的SELECT语句,例如,没有办法得到第一行、下一行或前10行,也不存在每次一行地处理所有行的简单方法(相对于成批地处理它们)。 有时,需要在检索…

Python clickhouse-driver 类库使用学习总结

实践环境 python3 .9.13 clickhouse-driver 0.2.9 实践操作 # -*- coding:utf-8 -*-import clickhouse_driverif __name__ == __main__:host = 192.168.88.131port = 9000 # 注意,不能使用默认的8123username = testaccpassword = test1234database = default# 连接方式1# con…

随波逐流工具使用_Week1

跟着大师傅的公众号做题的week1 来源以及说明 (文章主要是了解怎样使用长弓三皮大师傅的随波逐流工具,wp以及附件来自大师傅长弓三皮) (这周主要是做笔记的软件老是出现问题,有一些笔记有点乱,后面慢慢改进) 软件及题目下载 http://www.1o1o.xyz/bo_softdown.html CTF题目wr…

开源 - Ideal库 - 特殊时间扩展方法(三)

分享特殊时间获取的扩展方法,包括当天开始/结束时间、当前周/月/季度/年的第一天和最后一天等,附代码示例和单元测试,库将上传至Nuget,源码在代码库。书接上回,我们继续来分享一些关于特殊时间获取的常用扩展方法。01、获取当天的开始时间 当天的开始时间指00:00:00时刻,…

Vue2: v-for 联合 ref 使用, 对应引用信息为数组

MarkTime: 2024-06-03 00:21:47 LogTime: 2024-11-10 23:25:35说明问题:调用ref引用的时候, 好奇获取的时候为什么 有的返回的是对象, 有的返回的是数组 (如下图)版本:vue: 2.6.14源码 <!--已经省略掉大部分代码 只保留结构为说明 --> <template><div class=&qu…

Debug: setTimeout 使用做定时器时的错误函数传递方式

MarkTime: 2024-05-24 10:41:26 LogTime: 2024-11-10 14:55:53首先复习 setTimeout(): 语法: let timeId = setTimeout(func|code, [delay_millisecond]) 说明: 延时器. 延迟delay_millisecond后, 执行参数1setInterval(): 语法: let timeId = setInterval(func|code, [delay_…

Debug: calc() 未生效 = 内嵌样式表达式需使用空格分隔

MarkTime: 2024-06-25 17:10 LogTime: 2024-11-09 13:58:02结论calc()内的表达式 需要使用 空格分隔符, 即 更正 calc(100%-100px-10px); => calc(100% - 100px - 10px); 即可源<!-- 原错误代码 --> <div class="layout-search" style="width: 100%…

[云研发]腾讯云cloudstudio使用教程-记录1

cloudstudio在vscode中新建终端,使用nvidia-smi查看显卡与gpu情况,可知当前使用的显卡是T4的,显存有15GTalk is cheap. Show me the code

rip

题目链接:rip。 IDA 打开附件,进入到 main 函数,反编译后如下。留意到存在 gets 函数,因此存在栈溢出漏洞,经过动态调试,确定在输入 0x17 个字符后,即可覆盖到返回地址。同时,留意到存在 fun 函数,如下。因此,直接将程序执行流劫持到 fun 函数,即可 GetShell(此处需…

test_your_nc

题目链接:test_your_nc。 打开附件,进入 main 函数,IDA 反编译如下。因此直接连接即可 GetShell。

【docker应用】从Docker(k8s)镜像或者容器里提取jar包

引言 在docker或者k8s上运行了第三方的应用,很多时候我们都想知道运行流程,一般都会docker或者k8s容器中获取jar包。 那么该如何把里面的jar包提取出来呢? 其实有两种方式,分别为: 从镜像信息获取 进入容器获取从镜像信息获取 首先,查看镜像: docker image ls |grep <…