# 鴻蒙 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 動畫編程和符號處理的優秀教學案例。簡潔的代碼背后蘊含著豐富的交互設計智慧和性能優化技巧。

相關新聞

2026輕薄便攜筆記本推薦,差旅人士的全天候搭檔

2026輕薄便攜筆記本推薦,差旅人士的全天候搭檔

對于經常奔波于不同城市的商務人士而言,筆記本電腦幾乎是行李箱里的固定成員。一場跨城會議結束緊接著趕航班,在候機廳里處理緊急郵件,在高鐵上修改方案——這些場景下,續航就是生產力。那些號稱“長續航”的輕薄本,在…

2026/8/1 19:11:51 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應用材料(Applied Materials)公司生產的一款用于半導體設備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業用三相異步電機,適用于自動化設備及通用機械驅動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/1 0:09:33 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應用材料(Applied Materials)公司生產的一款用于半導體設備的I/O信號分配電路板。該型號(0100-02186)的核心特點如下:專用于Endura等半導體工藝腔室。集成信號路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動機是日本日清(Nissei)品牌的一款工業用三相異步電機,適用于自動化設備及通用機械驅動。該型號(FFMN-32L-10-T0 40AX)的核心特點如下:三相交流異步電動機。額定…

2026/8/1 0:09:33 閱讀更多