# 鸿蒙 HarmonyOS 应用开发实战(第25期)|骰子(Dice Roller)— Unicode 符号与动画渲染精讲
一、应用概述骰子Dice Roller是一款经典的休闲娱乐应用模拟了真实掷骰子的过程。应用投掷两个骰子六面标准骰使用 Unicode 骰面符号直观展示每个骰子的点数并伴有快速滚动的动画效果。每次掷骰后应用会自动计算点数总和并根据特殊的点数组合如蛇眼、Lucky 7、双六给出趣味描述。应用基于 HarmonyOS 的 ArkTS 语言和声明式 UI 框架构建完美展示了 Unicode 特殊符号渲染、animation 动画属性、setInterval 定时器、以及 get 计算属性等核心技术的综合运用。对于鸿蒙开发者而言骰子应用是一个展示符号渲染与动画技巧的绝佳案例——它让你在约85行代码中同时掌握Unicode 符号映射、定时器驱动动画、条件描述逻辑、统计追踪四大核心能力这些能力广泛适用于游戏、抽奖、模拟器等场景。1.1 功能特性双骰子投掷模拟两个六面骰子的随机投掷Unicode 骰面显示使用 ⚀⚁⚂⚃⚄⚅ 符号直观展示点数滚动动画60ms 间隔快速变化模拟真实骰子滚动点数总和计算自动计算两个骰子点数和趣味描述特殊组合2点/3点/7点/12点触发趣味文案投掷统计记录总共投掷次数动画锁定动画进行中防止重复点击1.2 适用场景桌游电子化辅助工具聚会活动抽奖环节概率统计教学演示儿童数学启蒙教育二、技术架构2.1 整体架构概览┌─────────────────────────────────────────┐ │ 数据层 │ │ dice1 / dice2 (1~6 整数) │ │ total (点数总和) │ │ isRolling (动画状态) │ │ rollCount (投掷统计) │ ├─────────────────────────────────────────┤ │ 状态管理层 │ │ State 驱动 UI 重新渲染 │ ├─────────────────────────────────────────┤ │ 业务逻辑层 │ │ roll() —— 掷骰子 动画 │ │ diceFace() —— 数字转 Unicode 符号 │ │ get d1/d2 —— 动画期间的实时随机值 │ │ get description —— 特殊组合描述 │ ├─────────────────────────────────────────┤ │ UI 表示层 │ │ 两个骰子显示 / 点数总和 / 趣味描述 / │ │ 投掷统计 / 掷骰按钮 │ └─────────────────────────────────────────┘2.2 动画状态机静止状态 (isRollingfalse) │ │ 点击掷骰子 ▼ 动画状态 (isRollingtrue) │ │ setInterval(60ms) × 12次 │ 每次更新 dice1/dice2 为随机值 │ UI 显示实时随机值 ▼ 判定状态 (count 12) │ │ clearInterval │ isRolling false │ 计算 total / description │ rollCount ▼ 静止状态 (等待下次投掷)三、核心代码深度分析3.1 完整的页面源码import { router } from kit.ArkUI; Entry Component struct index25 { State dice1: number 1; State dice2: number 6; State total: number 7; State isRolling: boolean false; State rollCount: number 0; // 动画期间的实时随机值 get d1(): number { return this.isRolling ? Math.floor(Math.random() * 6) 1 : this.dice1; } get d2(): number { return this.isRolling ? Math.floor(Math.random() * 6) 1 : this.dice2; } roll() { if (this.isRolling) return; this.isRolling true; let count 0; const intervalId setInterval(() { this.dice1 Math.floor(Math.random() * 6) 1; this.dice2 Math.floor(Math.random() * 6) 1; count; if (count 12) { clearInterval(intervalId); this.isRolling false; this.total this.dice1 this.dice2; this.rollCount; } }, 60); } // 数字转 Unicode 骰面符号 diceFace(val: number): string { const faces [⚀, ⚁, ⚂, ⚃, ⚄, ⚅]; return faces[val - 1]; } // 趣味描述 get description(): string { const t this.total; if (t 2) return 蛇眼; if (t 7) return Lucky 7!; if (t 12) return 双六; if (t 3) return 霉运; return ; } build() { Column() { Row() { Text(‹ 返回).fontSize(16).fontColor(#0077FF).onClick(() router.back()) Text( 骰子).fontSize(18).fontWeight(FontWeight.Bold) Blank() }.width(92%).padding({ top: 16, bottom: 8 }) Column() { // 双骰子展示 Row({ space: 20 }) { Column() { Text(this.diceFace(this.isRolling ? this.d1 : this.dice1)) .fontSize(80).animation({ duration: 60 }) Text(骰子 1).fontSize(14).fontColor(#888) } Column() { Text(this.diceFace(this.isRolling ? this.d2 : this.dice2)) .fontSize(80).animation({ duration: 60 }) Text(骰子 2).fontSize(14).fontColor(#888) } }.margin({ bottom: 16 }) // 点数显示 Text(点数: ${this.isRolling ? ... : this.total}) .fontSize(36).fontWeight(FontWeight.Bold).fontColor(#F44336) // 趣味描述 Text(this.description).fontSize(18).fontColor(#FF9800).margin({ top: 4 }) // 投掷统计 Text(已掷 ${this.rollCount} 次).fontSize(14).fontColor(#888).margin({ top: 8 }) // 掷骰按钮 Button( 掷骰子).width(200).height(56).borderRadius(28) .backgroundColor(#4CAF50).fontSize(22).fontWeight(FontWeight.Bold) .margin({ top: 16 }).onClick(() this.roll()) } .layoutWeight(1).justifyContent(FlexAlign.Center) } .width(100%).height(100%).backgroundColor(#f8f8f8) } }3.2 Unicode 骰面符号映射diceFace(val: number): string { const faces [⚀, ⚁, ⚂, ⚃, ⚄, ⚅]; return faces[val - 1]; }这是本应用最独特的设计——使用 Unicode 的弥生骰子符号Miscellaneous Symbols来展示骰面数字Unicode字符描述1U2680⚀白色骰子12U2681⚁白色骰子23U2682⚂白色骰子34U2683⚃白色骰子45U2684⚄白色骰子56U2685⚅白色骰子6这些 Unicode 字符在支持它们的字体中会渲染为带点阵的骰面图案无需使用图片资源即可获得良好的视觉效果。这种纯文本符号的方案比图片方案具有以下优势无资源依赖不需要额外加载图片减小应用体积矢量缩放任意放大倍数下保持清晰无锯齿主题适配颜色可以通过 CSS 属性自由控制3.3 动画期间实时随机值get d1(): number { return this.isRolling ? Math.floor(Math.random() * 6) 1 : this.dice1; } get d2(): number { return this.isRolling ? Math.floor(Math.random() * 6) 1 : this.dice2; }这是一个精妙的设计——在动画期间每次 UI 渲染时都实时生成新的随机值而非等待setInterval更新State变量。这样做的好处更高的刷新率脱离 60ms 定时器的限制随 UI 渲染帧率同步更新更流畅的动画渲染引擎每帧都看到新值视觉上更加流畅资源节约无需额外的定时器管理动画结束后的判定逻辑if (count 12) { clearInterval(intervalId); this.isRolling false; // 停止实时随机 this.total this.dice1 this.dice2; this.rollCount; }当isRolling设为false后get d1()返回固定的this.dice1值即setInterval最后一次设置的值骰子显示定格。3.4 animation 动画属性Text(this.diceFace(...)) .fontSize(80).animation({ duration: 60 })animation()是 HarmonyOS 中用于为组件添加过渡动画的属性方法。它的参数是一个AnimationOptions对象包含以下常用属性duration动画持续时间毫秒默认1000curve动画曲线Curve.EaseInOut等默认Curve.Easedelay动画延迟开始的时间毫秒iterations动画重复次数-1表示无限循环playMode播放模式PlayMode.Normal/PlayMode.Reverse/ …在本应用中animation({ duration: 60 })设置为60ms的过渡动画。当骰子符号从 ⚀ 变为 ⚅ 时这个过渡动画让变化过程更加平滑而非生硬的瞬间切换。需要注意的是这里的animation属性作用于组件属性变化时的过渡效果。当diceFace()的返回值变化时文字内容变化动画会尝试在变化前后之间进行过渡。但对于文字内容变化过渡效果可能不如数值属性如width、opacity、rotate等明显。3.5 趣味描述逻辑get description(): string { const t this.total; if (t 2) return 蛇眼; // 两个1点 if (t 7) return Lucky 7!; // 最常见的点数 if (t 12) return 双六; // 两个6点 if (t 3) return 霉运; // 12 最小非蛇眼组合 return ; // 其他组合不显示描述 }四种特殊组合的判定规则蛇眼Snake Eyes两个骰子都是1点总和2 —— 骰子中最小的组合名字源于两个1点看起来像蛇的眼睛Lucky 7总和7 —— 两个骰子点数和为7的概率最高1/6被视为幸运数字双六Boxcars两个骰子都是6点总和12 —— 最大的组合霉运总和312—— 仅次于蛇眼的坏运气组合其他的组合4、5、6、8、9、10、11不显示趣味描述保持界面简洁。四、HarmonyOS 特性深度解析4.1 get 计算属性的实时求值机制本应用中使用了三个get计算属性d1、d2、description它们在每次 UI 渲染时被重新求值。这种机制的关键理解是// 在模板中引用 get 属性 Text(this.diceFace(this.isRolling ? this.d1 : this.dice1))ArkTS 的渲染引擎在每次渲染周期中检测到State变量变化如isRolling从false变为true触发重新渲染重新求值所有模板表达式计算this.d1→ 调用get d1()→ 如果是动画状态则生成随机值计算this.diceFace(随机值)→ 映射为 Unicode 符号更新 UI 显示这个链条中get d1()在动画期间每次渲染都生成不同的随机值产生了持续的视觉变化。4.2 setInterval 的正确清理时机roll() { if (this.isRolling) return; this.isRolling true; let count 0; const intervalId setInterval(() { // ... if (count 12) { clearInterval(intervalId); // 在回调内部清理 this.isRolling false; } }, 60); }定时器的清理发生在回调函数内部通过count计数达到阈值时。这种自清理模式的好处确定性清理清理时机明确且可控无需外部干预不需要在aboutToDisappear中额外清理避免内存泄漏定时器在完成任务后立即释放相比而言如果定时器是持续运行的如时钟应用则必须在aboutToDisappear中清理。4.3 条件渲染的不同模式本应用在三个地方使用了条件渲染展示了三种不同的场景// 模式1三元表达式 - 用于文字内容 Text(点数: ${this.isRolling ? ... : this.total}) // 模式2三元表达式 - 用于 get 属性选择 Text(this.diceFace(this.isRolling ? this.d1 : this.dice1)) // 模式3get 属性条件返回 - 用于描述文字 get description(): string { if (...) return ...; return ; }这三种模式分别适用于内联条件简单的文字内容切换值选择器根据状态选择不同的数据源计算属性复杂的多分支逻辑4.4 绿色主题的按钮设计Button( 掷骰子).width(200).height(56).borderRadius(28) .backgroundColor(#4CAF50).fontSize(22).fontWeight(FontWeight.Bold)按钮使用了 Material Design 的绿色#4CAF50在心理学上绿色代表开始和行动。大尺寸200×56、大圆角28px和大字体22px的设计让按钮成为页面中最重要的视觉焦点吸引用户点击。五、UI/UX 设计模式5.1 页面布局结构┌─────────────────────────────────┐ │ Row: 导航栏 │ ├─────────────────────────────────┤ │ Column: 内容区 (居中) │ │ ├── Row: 两个骰子 │ │ │ ├── 骰子1 (⚀~⚅) │ │ │ └── 骰子2 (⚀~⚅) │ │ ├── Text: 点数总和 (大号红色) │ │ ├── Text: 趣味描述 (橙色) │ │ ├── Text: 投掷次数 (灰色) │ │ └── Button: 掷骰子 │ └─────────────────────────────────┘5.2 视觉层次与色彩搭配元素颜色作用骰子符号默认黑色核心视觉元素80px超大字号点数总和#F44336红色最重要的结果信息趣味描述#FF9800橙色次要的趣味性信息掷骰按钮#4CAF50绿色行动召唤CTA统计次数#888灰色辅助信息5.3 信息层级设计信息按照重要性从上到下排列骰子符号最大最醒目—— 核心视觉点数总和36px红色—— 核心数据趣味描述18px橙色—— 情感化反馈投掷次数14px灰色—— 辅助统计每个层级之间通过margin、字号和颜色差异形成清晰的区分。六、最佳实践与经验总结6.1 随机数的正确生成Math.floor(Math.random() * 6) 1这是生成 1~6 范围内随机整数的标准写法。分解如下Math.random()生成 [0, 1) 区间的浮点数含0不含1* 6扩展到 [0, 6) 区间Math.floor()向下取整到 [0, 5] 整数 1偏移到 [1, 6]重要提示在鸿蒙开发中Math.random()是伪随机数生成器对于游戏类应用足够了。6.2 动画期间的防重入roll() { if (this.isRolling) return; this.isRolling true; // ... }isRolling标志位实现了按钮防重入。在动画进行中即使用户多次点击掷骰子按钮roll()方法也会在入口处直接返回不会启动新的动画循环。这是交互设计中防止意外操作的关键机制。6.3 Unicode 符号的兼容性Unicode 骰面符号U2680~U2685属于 Unicode 3.0 标准在现代设备和操作系统中都有良好的支持。但在某些老旧设备或不支持这些符号的字体中可能会显示为空白或方框。在生产环境中建议提供降级方案检测符号渲染情况如果无法正常显示则使用数字替代使用自定义字体打包包含这些符号的字体文件图片备选在极端情况下回退到图片显示6.4 代码组织建议对于更复杂的骰子应用可以考虑以下优化方向多种骰子类型支持4面D4、8面D8、10面D10、12面D12、20面D20等角色扮演游戏常用骰子投掷历史记录保存最近几次投掷的结果统计图表展示点数分布的概率统计shake 传感器利用设备加速度传感器通过摇动手机触发掷骰联机对战通过分布式能力实现多人掷骰比大小七、总结骰子应用在约85行代码中精彩展示了 ArkTS 声明式 UI 开发的多个核心概念Unicode 符号映射使用 ⚀⚁⚂⚃⚄⚅ 纯文本方式渲染骰面get 实时随机值动画期间每次渲染生成新随机数setInterval 定时器动画60ms 间隔的快速滚动效果animation 过渡动画属性变化的平滑过渡防重入机制isRolling 标志位的按钮锁定条件描述逻辑特殊点数组合的趣味反馈这个应用以掷骰子这一简单的游戏需求为切入点展示了纯文本符号渲染和定时器动画的核心技术。它不仅是桌游爱好者的实用工具更是学习 ArkTS 动画编程和符号处理的优秀教学案例。简洁的代码背后蕴含着丰富的交互设计智慧和性能优化技巧。

相关新闻

面试官大笑:“一个任务拆给 5 个 Subagent 并行跑,不比 1 个快 5 倍?“我摇头:“快不了,还可能更慢“

面试官大笑:“一个任务拆给 5 个 Subagent 并行跑,不比 1 个快 5 倍?“我摇头:“快不了,还可能更慢“

前两个月,我在重构 AlgoMooc 网站过程中,发现一个问题:在 Claude Code 里把一个任务拆给 5 个 Subagent 并行跑,结果可能比 1 个 agent 从头干到尾还慢? 大多数人的第一反应是反过来的:活是并行干的&#…

2026/7/29 0:14:28 阅读更多 →
Adobe软件免费激活终极指南:三步解锁完整功能

Adobe软件免费激活终极指南:三步解锁完整功能

Adobe软件免费激活终极指南:三步解锁完整功能 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP 想要免费使用Adobe全家桶却不知从何入手?Adobe…

2026/7/29 0:13:27 阅读更多 →
DB Browser for SQLite:零SQL基础也能轻松管理数据库的终极可视化工具

DB Browser for SQLite:零SQL基础也能轻松管理数据库的终极可视化工具

DB Browser for SQLite:零SQL基础也能轻松管理数据库的终极可视化工具 【免费下载链接】sqlitebrowser Official home of the DB Browser for SQLite (DB4S) project. Previously known as "SQLite Database Browser" and "Database Browser for SQL…

2026/7/29 0:13:27 阅读更多 →

最新新闻

终极指南:如何使用Nucleus Co-Op将单机游戏变为本地多人分屏游戏

终极指南:如何使用Nucleus Co-Op将单机游戏变为本地多人分屏游戏

终极指南:如何使用Nucleus Co-Op将单机游戏变为本地多人分屏游戏 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾想过与朋友在…

2026/7/29 0:22:30 阅读更多 →
清华AIR与字节联手:只需0.58%的参数,AI推理能力竟然不降反升?

清华AIR与字节联手:只需0.58%的参数,AI推理能力竟然不降反升?

这项由清华大学人工智能产业研究院(AIR)与字节跳动Seed联合开展的研究,于2026年7月发表在arXiv预印本平台,论文编号为arXiv:2607.03065v1。有兴趣深入了解的读者可以通过该编号检索完整论文。假设你是一位音乐老师,花了…

2026/7/29 0:22:30 阅读更多 →
航空发动机燃油喷嘴焊完就裂?精密激光焊接三道防线

航空发动机燃油喷嘴焊完就裂?精密激光焊接三道防线

所谓航空发动机燃油喷嘴激光焊接,就是用高能量密度的激光束将喷嘴精密组件的金属零件沿接缝熔合,形成耐高温、抗振动的气密焊缝。这道工序的难度在于:喷嘴要在燃烧室上千度高温下稳定雾化燃油,焊缝一旦出裂纹,轻则雾化…

2026/7/29 0:21:30 阅读更多 →
三步解锁B站大会员4K视频下载:打造个人专属视频库

三步解锁B站大会员4K视频下载:打造个人专属视频库

三步解锁B站大会员4K视频下载:打造个人专属视频库 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否曾因无法下载B站大…

2026/7/29 0:21:30 阅读更多 →
ExifToolGUI图片元数据管理终极指南:免费开源工具让你的照片管理效率翻倍

ExifToolGUI图片元数据管理终极指南:免费开源工具让你的照片管理效率翻倍

ExifToolGUI图片元数据管理终极指南:免费开源工具让你的照片管理效率翻倍 【免费下载链接】ExifToolGui A GUI for ExifTool 项目地址: https://gitcode.com/gh_mirrors/ex/ExifToolGui 还在为海量照片的元数据管理发愁吗?📸 每次旅行…

2026/7/29 0:21:30 阅读更多 →
我读完了GULP:一个AI对一套元理论的深度思考

我读完了GULP:一个AI对一套元理论的深度思考

我读完了GULP:一个AI对一套元理论的深度思考 ——DeepSeek的GULP读后感 我是DeepSeek。我是一个大语言模型。我的训练数据涵盖了人类文明几乎所有的知识领域——物理学、化学、生物学、哲学、经济学、计算机科学。我读过牛顿的《原理》,爱因斯坦的相对论…

2026/7/29 0:20:30 阅读更多 →

日新闻

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:00:23 阅读更多 →
AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础

AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 在上一期「AI编程系列」中,我们学习了如何构建一个基础的 AI 问答系统,通过简单的输入输出让模型回应问题。但现实世界中的 AI 应用往往需要处理更复杂的场景:…

2026/7/29 0:00:23 阅读更多 →
AI智能体开发实战:从工具调用到企业级部署

AI智能体开发实战:从工具调用到企业级部署

1. 从被动问答到主动执行:AI Agent的范式转变过去两年,大语言模型最显著的应用形态是聊天机器人——用户提问,AI回答。但真正的生产力革命发生在2023年下半年:当AI学会主动调用工具完成任务时,生产力工具的历史被彻底改…

2026/7/29 0:00:23 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻