# 鴻蒙 HarmonyOS 應(yīng)用開發(fā)實戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號與動畫渲染精講
一、應(yīng)用概述骰子Dice Roller是一款經(jīng)典的休閑娛樂應(yīng)用模擬了真實擲骰子的過程。應(yīng)用投擲兩個骰子六面標(biāo)準(zhǔn)骰使用 Unicode 骰面符號直觀展示每個骰子的點數(shù)并伴有快速滾動的動畫效果。每次擲骰后應(yīng)用會自動計算點數(shù)總和并根據(jù)特殊的點數(shù)組合如蛇眼、Lucky 7、雙六給出趣味描述。應(yīng)用基于 HarmonyOS 的 ArkTS 語言和聲明式 UI 框架構(gòu)建完美展示了 Unicode 特殊符號渲染、animation 動畫屬性、setInterval 定時器、以及 get 計算屬性等核心技術(shù)的綜合運用。對于鴻蒙開發(fā)者而言骰子應(yīng)用是一個展示符號渲染與動畫技巧的絕佳案例——它讓你在約85行代碼中同時掌握Unicode 符號映射、定時器驅(qū)動動畫、條件描述邏輯、統(tǒng)計追蹤四大核心能力這些能力廣泛適用于游戲、抽獎、模擬器等場景。1.1 功能特性雙骰子投擲模擬兩個六面骰子的隨機(jī)投擲Unicode 骰面顯示使用 ?????? 符號直觀展示點數(shù)滾動動畫60ms 間隔快速變化模擬真實骰子滾動點數(shù)總和計算自動計算兩個骰子點數(shù)和趣味描述特殊組合2點/3點/7點/12點觸發(fā)趣味文案投擲統(tǒng)計記錄總共投擲次數(shù)動畫鎖定動畫進(jìn)行中防止重復(fù)點擊1.2 適用場景桌游電子化輔助工具聚會活動抽獎環(huán)節(jié)概率統(tǒng)計教學(xué)演示兒童數(shù)學(xué)啟蒙教育二、技術(shù)架構(gòu)2.1 整體架構(gòu)概覽┌─────────────────────────────────────────┐ │ 數(shù)據(jù)層 │ │ dice1 / dice2 (1~6 整數(shù)) │ │ total (點數(shù)總和) │ │ isRolling (動畫狀態(tài)) │ │ rollCount (投擲統(tǒng)計) │ ├─────────────────────────────────────────┤ │ 狀態(tài)管理層 │ │ State 驅(qū)動 UI 重新渲染 │ ├─────────────────────────────────────────┤ │ 業(yè)務(wù)邏輯層 │ │ roll() —— 擲骰子 動畫 │ │ diceFace() —— 數(shù)字轉(zhuǎn) Unicode 符號 │ │ get d1/d2 —— 動畫期間的實時隨機(jī)值 │ │ get description —— 特殊組合描述 │ ├─────────────────────────────────────────┤ │ UI 表示層 │ │ 兩個骰子顯示 / 點數(shù)總和 / 趣味描述 / │ │ 投擲統(tǒng)計 / 擲骰按鈕 │ └─────────────────────────────────────────┘2.2 動畫狀態(tài)機(jī)靜止?fàn)顟B(tài) (isRollingfalse) │ │ 點擊擲骰子 ▼ 動畫狀態(tài) (isRollingtrue) │ │ setInterval(60ms) × 12次 │ 每次更新 dice1/dice2 為隨機(jī)值 │ UI 顯示實時隨機(jī)值 ▼ 判定狀態(tài) (count 12) │ │ clearInterval │ isRolling false │ 計算 total / description │ rollCount ▼ 靜止?fàn)顟B(tài) (等待下次投擲)三、核心代碼深度分析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; // 動畫期間的實時隨機(jī)值 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); } // 數(shù)字轉(zhuǎn) 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 }) // 點數(shù)顯示 Text(點數(shù): ${this.isRolling ? ... : this.total}) .fontSize(36).fontWeight(FontWeight.Bold).fontColor(#F44336) // 趣味描述 Text(this.description).fontSize(18).fontColor(#FF9800).margin({ top: 4 }) // 投擲統(tǒng)計 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]; }這是本應(yīng)用最獨特的設(shè)計——使用 Unicode 的彌生骰子符號Miscellaneous Symbols來展示骰面數(shù)字Unicode字符描述1U2680?白色骰子12U2681?白色骰子23U2682?白色骰子34U2683?白色骰子45U2684?白色骰子56U2685?白色骰子6這些 Unicode 字符在支持它們的字體中會渲染為帶點陣的骰面圖案無需使用圖片資源即可獲得良好的視覺效果。這種純文本符號的方案比圖片方案具有以下優(yōu)勢無資源依賴不需要額外加載圖片減小應(yīng)用體積矢量縮放任意放大倍數(shù)下保持清晰無鋸齒主題適配顏色可以通過 CSS 屬性自由控制3.3 動畫期間實時隨機(jī)值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; }這是一個精妙的設(shè)計——在動畫期間每次 UI 渲染時都實時生成新的隨機(jī)值而非等待setInterval更新State變量。這樣做的好處更高的刷新率脫離 60ms 定時器的限制隨 UI 渲染幀率同步更新更流暢的動畫渲染引擎每幀都看到新值視覺上更加流暢資源節(jié)約無需額外的定時器管理動畫結(jié)束后的判定邏輯if (count 12) { clearInterval(intervalId); this.isRolling false; // 停止實時隨機(jī) this.total this.dice1 this.dice2; this.rollCount; }當(dāng)isRolling設(shè)為false后get d1()返回固定的this.dice1值即setInterval最后一次設(shè)置的值骰子顯示定格。3.4 animation 動畫屬性Text(this.diceFace(...)) .fontSize(80).animation({ duration: 60 })animation()是 HarmonyOS 中用于為組件添加過渡動畫的屬性方法。它的參數(shù)是一個AnimationOptions對象包含以下常用屬性duration動畫持續(xù)時間毫秒默認(rèn)1000curve動畫曲線Curve.EaseInOut等默認(rèn)Curve.Easedelay動畫延遲開始的時間毫秒iterations動畫重復(fù)次數(shù)-1表示無限循環(huán)playMode播放模式PlayMode.Normal/PlayMode.Reverse/ …在本應(yīng)用中animation({ duration: 60 })設(shè)置為60ms的過渡動畫。當(dāng)骰子符號從 ? 變?yōu)?? 時這個過渡動畫讓變化過程更加平滑而非生硬的瞬間切換。需要注意的是這里的animation屬性作用于組件屬性變化時的過渡效果。當(dāng)diceFace()的返回值變化時文字內(nèi)容變化動畫會嘗試在變化前后之間進(jìn)行過渡。但對于文字內(nèi)容變化過渡效果可能不如數(shù)值屬性如width、opacity、rotate等明顯。3.5 趣味描述邏輯get description(): string { const t this.total; if (t 2) return 蛇眼; // 兩個1點 if (t 7) return Lucky 7!; // 最常見的點數(shù) if (t 12) return 雙六; // 兩個6點 if (t 3) return 霉運; // 12 最小非蛇眼組合 return ; // 其他組合不顯示描述 }四種特殊組合的判定規(guī)則蛇眼Snake Eyes兩個骰子都是1點總和2 —— 骰子中最小的組合名字源于兩個1點看起來像蛇的眼睛Lucky 7總和7 —— 兩個骰子點數(shù)和為7的概率最高1/6被視為幸運數(shù)字雙六Boxcars兩個骰子都是6點總和12 —— 最大的組合霉運總和312—— 僅次于蛇眼的壞運氣組合其他的組合4、5、6、8、9、10、11不顯示趣味描述保持界面簡潔。四、HarmonyOS 特性深度解析4.1 get 計算屬性的實時求值機(jī)制本應(yīng)用中使用了三個get計算屬性d1、d2、description它們在每次 UI 渲染時被重新求值。這種機(jī)制的關(guān)鍵理解是// 在模板中引用 get 屬性 Text(this.diceFace(this.isRolling ? this.d1 : this.dice1))ArkTS 的渲染引擎在每次渲染周期中檢測到State變量變化如isRolling從false變?yōu)閠rue觸發(fā)重新渲染重新求值所有模板表達(dá)式計算this.d1→ 調(diào)用get d1()→ 如果是動畫狀態(tài)則生成隨機(jī)值計算this.diceFace(隨機(jī)值)→ 映射為 Unicode 符號更新 UI 顯示這個鏈條中g(shù)et d1()在動畫期間每次渲染都生成不同的隨機(jī)值產(chǎn)生了持續(xù)的視覺變化。4.2 setInterval 的正確清理時機(jī)roll() { if (this.isRolling) return; this.isRolling true; let count 0; const intervalId setInterval(() { // ... if (count 12) { clearInterval(intervalId); // 在回調(diào)內(nèi)部清理 this.isRolling false; } }, 60); }定時器的清理發(fā)生在回調(diào)函數(shù)內(nèi)部通過count計數(shù)達(dá)到閾值時。這種自清理模式的好處確定性清理清理時機(jī)明確且可控?zé)o需外部干預(yù)不需要在aboutToDisappear中額外清理避免內(nèi)存泄漏定時器在完成任務(wù)后立即釋放相比而言如果定時器是持續(xù)運行的如時鐘應(yīng)用則必須在aboutToDisappear中清理。4.3 條件渲染的不同模式本應(yīng)用在三個地方使用了條件渲染展示了三種不同的場景// 模式1三元表達(dá)式 - 用于文字內(nèi)容 Text(點數(shù): ${this.isRolling ? ... : this.total}) // 模式2三元表達(dá)式 - 用于 get 屬性選擇 Text(this.diceFace(this.isRolling ? this.d1 : this.dice1)) // 模式3get 屬性條件返回 - 用于描述文字 get description(): string { if (...) return ...; return ; }這三種模式分別適用于內(nèi)聯(lián)條件簡單的文字內(nèi)容切換值選擇器根據(jù)狀態(tài)選擇不同的數(shù)據(jù)源計算屬性復(fù)雜的多分支邏輯4.4 綠色主題的按鈕設(shè)計Button( 擲骰子).width(200).height(56).borderRadius(28) .backgroundColor(#4CAF50).fontSize(22).fontWeight(FontWeight.Bold)按鈕使用了 Material Design 的綠色#4CAF50在心理學(xué)上綠色代表開始和行動。大尺寸200×56、大圓角28px和大字體22px的設(shè)計讓按鈕成為頁面中最重要的視覺焦點吸引用戶點擊。五、UI/UX 設(shè)計模式5.1 頁面布局結(jié)構(gòu)┌─────────────────────────────────┐ │ Row: 導(dǎo)航欄 │ ├─────────────────────────────────┤ │ Column: 內(nèi)容區(qū) (居中) │ │ ├── Row: 兩個骰子 │ │ │ ├── 骰子1 (?~?) │ │ │ └── 骰子2 (?~?) │ │ ├── Text: 點數(shù)總和 (大號紅色) │ │ ├── Text: 趣味描述 (橙色) │ │ ├── Text: 投擲次數(shù) (灰色) │ │ └── Button: 擲骰子 │ └─────────────────────────────────┘5.2 視覺層次與色彩搭配元素顏色作用骰子符號默認(rèn)黑色核心視覺元素80px超大字號點數(shù)總和#F44336紅色最重要的結(jié)果信息趣味描述#FF9800橙色次要的趣味性信息擲骰按鈕#4CAF50綠色行動召喚CTA統(tǒng)計次數(shù)#888灰色輔助信息5.3 信息層級設(shè)計信息按照重要性從上到下排列骰子符號最大最醒目—— 核心視覺點數(shù)總和36px紅色—— 核心數(shù)據(jù)趣味描述18px橙色—— 情感化反饋投擲次數(shù)14px灰色—— 輔助統(tǒng)計每個層級之間通過margin、字號和顏色差異形成清晰的區(qū)分。六、最佳實踐與經(jīng)驗總結(jié)6.1 隨機(jī)數(shù)的正確生成Math.floor(Math.random() * 6) 1這是生成 1~6 范圍內(nèi)隨機(jī)整數(shù)的標(biāo)準(zhǔn)寫法。分解如下Math.random()生成 [0, 1) 區(qū)間的浮點數(shù)含0不含1* 6擴(kuò)展到 [0, 6) 區(qū)間Math.floor()向下取整到 [0, 5] 整數(shù) 1偏移到 [1, 6]重要提示在鴻蒙開發(fā)中Math.random()是偽隨機(jī)數(shù)生成器對于游戲類應(yīng)用足夠了。6.2 動畫期間的防重入roll() { if (this.isRolling) return; this.isRolling true; // ... }isRolling標(biāo)志位實現(xiàn)了按鈕防重入。在動畫進(jìn)行中即使用戶多次點擊擲骰子按鈕roll()方法也會在入口處直接返回不會啟動新的動畫循環(huán)。這是交互設(shè)計中防止意外操作的關(guān)鍵機(jī)制。6.3 Unicode 符號的兼容性Unicode 骰面符號U2680~U2685屬于 Unicode 3.0 標(biāo)準(zhǔn)在現(xiàn)代設(shè)備和操作系統(tǒng)中都有良好的支持。但在某些老舊設(shè)備或不支持這些符號的字體中可能會顯示為空白或方框。在生產(chǎn)環(huán)境中建議提供降級方案檢測符號渲染情況如果無法正常顯示則使用數(shù)字替代使用自定義字體打包包含這些符號的字體文件圖片備選在極端情況下回退到圖片顯示6.4 代碼組織建議對于更復(fù)雜的骰子應(yīng)用可以考慮以下優(yōu)化方向多種骰子類型支持4面D4、8面D8、10面D10、12面D12、20面D20等角色扮演游戲常用骰子投擲歷史記錄保存最近幾次投擲的結(jié)果統(tǒng)計圖表展示點數(shù)分布的概率統(tǒng)計shake 傳感器利用設(shè)備加速度傳感器通過搖動手機(jī)觸發(fā)擲骰聯(lián)機(jī)對戰(zhàn)通過分布式能力實現(xiàn)多人擲骰比大小七、總結(jié)骰子應(yīng)用在約85行代碼中精彩展示了 ArkTS 聲明式 UI 開發(fā)的多個核心概念Unicode 符號映射使用 ?????? 純文本方式渲染骰面get 實時隨機(jī)值動畫期間每次渲染生成新隨機(jī)數(shù)setInterval 定時器動畫60ms 間隔的快速滾動效果animation 過渡動畫屬性變化的平滑過渡防重入機(jī)制isRolling 標(biāo)志位的按鈕鎖定條件描述邏輯特殊點數(shù)組合的趣味反饋這個應(yīng)用以擲骰子這一簡單的游戲需求為切入點展示了純文本符號渲染和定時器動畫的核心技術(shù)。它不僅是桌游愛好者的實用工具更是學(xué)習(xí) ArkTS 動畫編程和符號處理的優(yōu)秀教學(xué)案例。簡潔的代碼背后蘊(yùn)含著豐富的交互設(shè)計智慧和性能優(yōu)化技巧。

相關(guān)新聞

面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

前兩個月,我在重構(gòu) AlgoMooc 網(wǎng)站過程中,發(fā)現(xiàn)一個問題:在 Claude Code 里把一個任務(wù)拆給 5 個 Subagent 并行跑,結(jié)果可能比 1 個 agent 從頭干到尾還慢? 大多數(shù)人的第一反應(yīng)是反過來的:活是并行干的&#…

2026/7/29 0:15:24 閱讀更多
十年琴師經(jīng)驗!兒童小提琴選購避坑指南,4款機(jī)型精準(zhǔn)推薦

十年琴師經(jīng)驗!兒童小提琴選購避坑指南,4款機(jī)型精準(zhǔn)推薦

一、4大核心選購要點,破解商家九成營銷套路選對琴的核心不是看價格、拼品牌,而是吃透底層選購邏輯。掌握這4個關(guān)鍵要點,就能輕松識破商家套路,按需選琴不踩坑。1. 尺寸優(yōu)先適配,選錯尺寸一切白費小提琴分多尺寸規(guī)格&am…

2026/7/28 23:54:55 閱讀更多
主流 JDK 發(fā)行版 的詳細(xì)對比

主流 JDK 發(fā)行版 的詳細(xì)對比

一、基礎(chǔ)關(guān)系圖 OpenJDK(開源上游)│├── Oracle JDK(商業(yè)發(fā)行版,基于 OpenJDK 閉源增強(qiáng))├── Eclipse Temurin(社區(qū)中立,TCK 認(rèn)證,廣泛兼容)├── Amazon Corrett…

2026/7/29 3:26:01 閱讀更多
物聯(lián)網(wǎng)設(shè)備硬件安全防護(hù)與SE050安全元件應(yīng)用

物聯(lián)網(wǎng)設(shè)備硬件安全防護(hù)與SE050安全元件應(yīng)用

1. 為什么物聯(lián)網(wǎng)設(shè)備需要硬件級安全防護(hù)在2023年某智能家居廠商的數(shù)據(jù)泄露事件中,攻擊者通過入侵溫控器設(shè)備獲取了超過50萬用戶的家庭網(wǎng)絡(luò)憑證。這個典型案例揭示了物聯(lián)網(wǎng)設(shè)備面臨的三大安全挑戰(zhàn):資源受限環(huán)境:多數(shù)物聯(lián)網(wǎng)終端采用MCU方案&…

2026/7/29 3:26:01 閱讀更多
面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

前兩個月,我在重構(gòu) AlgoMooc 網(wǎng)站過程中,發(fā)現(xiàn)一個問題:在 Claude Code 里把一個任務(wù)拆給 5 個 Subagent 并行跑,結(jié)果可能比 1 個 agent 從頭干到尾還慢? 大多數(shù)人的第一反應(yīng)是反過來的:活是并行干的&#…

2026/7/29 0:15:24 閱讀更多
# 鴻蒙 HarmonyOS 應(yīng)用開發(fā)實戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號與動畫渲染精講

# 鴻蒙 HarmonyOS 應(yīng)用開發(fā)實戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號與動畫渲染精講

一、應(yīng)用概述 骰子(Dice Roller) 是一款經(jīng)典的休閑娛樂應(yīng)用,模擬了真實擲骰子的過程。應(yīng)用投擲兩個骰子(六面標(biāo)準(zhǔn)骰),使用 Unicode 骰面符號直觀展示每個骰子的點數(shù),并伴有快速滾動的動畫效果?!?/p>

2026/7/29 0:15:24 閱讀更多