` 中的 `
` 會是什麼顏色?
+```css
+div { color: blue; }
+.special { color: green; }
+h1 { color: red; }
+```
+*答案:紅色(元素選擇器直接針對 h1)*
+
+## 精通 CSS 選擇器
+
+CSS 選擇器是針對特定元素應用樣式的方式。它就像給出精確方向,與其說「那棟房子」,不如說「楓樹街上紅門的藍色房子」。
-## CSS 選擇器
+CSS 有多種精確程度,選擇正確的選擇器就像挑選合適工具。有時你想給整區所有門塗色,有時只要針對一扇門。
-### 標籤
+### 元素選擇器(標籤)
-到目前為止,你的 `style.css` 檔案中只為少數標籤設置了樣式,應用程式看起來有些奇怪:
+元素選擇器根據標籤名稱標的 HTML 元素,適合設定廣泛適用的基礎樣式:
-```CSS
+```css
body {
- font-family: helvetica, arial, sans-serif;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+ margin: 0;
+ padding: 0;
}
h1 {
- color: #3a241d;
- text-align: center;
+ color: #3a241d;
+ text-align: center;
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
}
```
-這種為標籤設置樣式的方法可以控制單一元素,但你需要控制玻璃缸中多個植物的樣式。為此,你需要利用 CSS 選擇器。
+**理解這些樣式:**
+- **對整頁** 用 `body` 設定一致的字型排版
+- **移除** 瀏覽器預設的邊距與內距,方便控制
+- **為** 所有標題元素設定顏色、對齊與間距
+- **使用** `rem` 單位,確保字型大小可延展且易讀
-### ID
+元素選擇器非常適合設定通用風格,但對於 terrarium 內部像植物這類個別元件,需要更細緻選擇器。
-為左側和右側容器添加一些樣式。由於標記中只有一個左側容器和一個右側容器,因此它們被賦予了 ID。使用 `#` 來設置樣式:
+### ID 選擇器:獨特元素
-```CSS
+ID 選擇器使用 `#`,針對具有特定 `id` 屬性的元素。因 ID 在頁面中應唯一,非常適合為獨特元素(如左、右兩邊的植物容器)設定樣式。
+
+讓我們設計 terrarium 側邊容器的樣式,放置植物:
+
+```css
#left-container {
- background-color: #eee;
- width: 15%;
- left: 0px;
- top: 0px;
- position: absolute;
- height: 100%;
- padding: 10px;
+ background-color: #f5f5f5;
+ width: 15%;
+ left: 0;
+ top: 0;
+ position: absolute;
+ height: 100vh;
+ padding: 1rem;
+ box-sizing: border-box;
}
#right-container {
- background-color: #eee;
- width: 15%;
- right: 0px;
- top: 0px;
- position: absolute;
- height: 100%;
- padding: 10px;
+ background-color: #f5f5f5;
+ width: 15%;
+ right: 0;
+ top: 0;
+ position: absolute;
+ height: 100vh;
+ padding: 1rem;
+ box-sizing: border-box;
}
```
-在這裡,你使用絕對定位將這些容器放置在螢幕的最左側和最右側,並使用百分比設置其寬度,以便它們可以適應小型行動裝置螢幕。
+**此段程式碼成果:**
+- **用** `absolute` 定位把容器固定在左右兩側
+- **使用** `vh`(視窗高度)單位製作響應式高度
+- **設定** `box-sizing: border-box`,包含 padding 計算寬度
+- **移除** `px` 單位的零值,使程式碼更乾淨
+- **搭配** 柔和背景色,較不刺眼
-✅ 這段代碼有些重複,因此不符合“DRY”(Don't Repeat Yourself,不要重複自己)的原則;你能找到更好的方法來設置這些 ID 的樣式嗎?也許可以結合 ID 和類?你需要更改標記並重構 CSS:
+✅ **程式碼質量挑戰**:此 CSS 違反 DRY(不要重複自己)原則,你能用 ID 和類別混合重構它嗎?
+**改良方法:**
```html
+
```
-### 類別
+```css
+.container {
+ background-color: #f5f5f5;
+ width: 15%;
+ top: 0;
+ position: absolute;
+ height: 100vh;
+ padding: 1rem;
+ box-sizing: border-box;
+}
-在上面的例子中,你為螢幕上的兩個唯一元素設置了樣式。如果你希望樣式應用於螢幕上的多個元素,可以使用 CSS 類別。為左側和右側容器中的植物設置樣式。
+#left-container {
+ left: 0;
+}
-注意,HTML 標記中的每個植物都有 ID 和類別的組合。這裡的 ID 是供稍後添加的 JavaScript 使用,用於操作玻璃缸植物的位置。而類別則為所有植物提供了統一的樣式。
+#right-container {
+ right: 0;
+}
+```
+### 類別選擇器:可復用樣式
+
+類別選擇器用 `.` 表示,適合將相同樣式套用到多個元素。與 ID 不同,類別可多處重複使用,非常適合樣式一致性的模式。
+
+在 terrarium 裡,每株植物需要共用樣式,但位置不同。可用類別分享樣式,ID 定位。
+
+**這是每株植物的 HTML 結構:**
```html
-

+
```
-將以下代碼添加到你的 `style.css` 檔案中:
+**重點說明:**
+- **用** `class="plant-holder"` 統一容器樣式
+- **用** `class="plant"` 統一植物圖像樣式與行為
+- **用** 唯一 `id="plant1"` 作特定定位與 JavaScript 操作
+- **使用** 描述性 alt 文字供輔助工具使用
+
+接著把這些樣式加進 `style.css`:
-```CSS
+```css
.plant-holder {
- position: relative;
- height: 13%;
- left: -10px;
+ position: relative;
+ height: 13%;
+ left: -0.6rem;
}
.plant {
- position: absolute;
- max-width: 150%;
- max-height: 150%;
- z-index: 2;
+ position: absolute;
+ max-width: 150%;
+ max-height: 150%;
+ z-index: 2;
+ transition: transform 0.3s ease;
+}
+
+.plant:hover {
+ transform: scale(1.05);
}
```
-在這段代碼中,值得注意的是相對定位和絕對定位的混合使用,我們會在下一節中詳細介紹。請注意高度是如何以百分比處理的:
+**解析這些樣式:**
+- **為** plant holder 設定相對定位,建立定位情境
+- **每個** plant holder 高度 13%,確保所有植物垂直可見且不需捲動
+- **輕微** 左移容器,更好對齊植物
+- **植物** 利用最大寬高限制,自主縮放保持比例
+- **使用** `z-index` 將植物置於 terrarium 其他元素之上
+- **加入** 平滑變化的懸停效果,提升互動感
+
+✅ **批判思考**:為什麼同時要有 `.plant-holder` 和 `.plant`?若只用一個會怎樣?
+
+> 💡 **設計模式**:容器 `.plant-holder` 控制佈局和定位,內容 `.plant` 控制外觀與縮放。分工讓程式碼更易維護與彈性。
+
+## CSS 定位原理
+
+CSS 定位就像舞台導演,指揮每個角色在哪站位、如何移動。有些角色遵循一般規則,有些角色需要特定定位才能呈現戲劇效果。
+
+一旦明白定位,許多佈局問題都迎刃而解。想要不動的導覽列?定位辦得到。想要具體位置的提示工具?定位同樣沒問題。
+
+### 五種定位值
+
+```mermaid
+quadrantChart
+ title CSS 定位策略
+ x-axis 文件流程 --> 從流程中移除
+ y-axis 靜態定位 --> 精確控制
+ quadrant-1 絕對定位
+ quadrant-2 固定定位
+ quadrant-3 靜態定位
+ quadrant-4 黏性定位
+
+ Static: [0.2, 0.2]
+ Relative: [0.3, 0.6]
+ Absolute: [0.8, 0.8]
+ Fixed: [0.9, 0.7]
+ Sticky: [0.5, 0.9]
+```
+| 定位值 | 行為 | 使用場合 |
+|----------------|----------|----------|
+| `static` | 預設流,忽略 top/left/right/bottom | 正常文件佈局 |
+| `relative` | 相對本身正常位置定位 | 小幅調整,建立定位上下文 |
+| `absolute` | 相對最近已定位祖先定位 | 精確擺放,疊加效果 |
+| `fixed` | 相對視窗定位 | 固定導覽列、浮動元素 |
+| `sticky` | 根據捲動切換相對與固定 | 捲動置頂標頭 |
+
+### 我們的 terrarium 定位策略
+
+terrarium 應用多種類型定位,做出目標佈局:
+
+```css
+/* Container positioning */
+.container {
+ position: absolute; /* Removes from normal flow */
+ /* ... other styles ... */
+}
-你將植物容器的高度設置為 13%,這是一個不錯的數值,確保所有植物都能顯示在每個垂直容器中,而不需要滾動。
+/* Plant holder positioning */
+.plant-holder {
+ position: relative; /* Creates positioning context */
+ /* ... other styles ... */
+}
-你將植物容器向左移動,使植物在容器內更居中。由於圖片有大量透明背景,為了讓它們更容易拖動,需要向左移動以更好地適應螢幕。
+/* Plant positioning */
+.plant {
+ position: absolute; /* Allows precise placement within holder */
+ /* ... other styles ... */
+}
+```
-然後,植物本身的最大寬度設置為 150%。這樣可以讓它隨著瀏覽器縮小而縮小。嘗試調整瀏覽器大小,植物會保持在容器內,但會縮小以適應。
+**解讀定位策略:**
+- **絕對定位容器** 脫離文件流,固定於螢幕邊緣
+- **相對定位植物容器** 建立定位上下文,仍保留文件流
+- **絕對定位植物** 可精準定位於其相對容器內
+- **此組合** 可讓植物垂直堆疊,且可個別定位
+
+> 🎯 **重要原因**:`plant` 元素需絕對定位,才能在下一課實作拖拉功能。絕對定位將它們從正常佈局中抽離,使拖放互動成為可能。
+
+✅ **實驗時間**:嘗試替換定位值並觀察結果:
+- 若將 `.container` 從 `absolute` 改為 `relative` 會怎樣?
+- 如果 `.plant-holder` 使用 `absolute` 而不是 `relative`,佈局會有什麼變化?
+- 當你將 `.plant` 改成 `relative` 定位時會發生什麼?
+
+### 🔄 **教學檢查點**
+**CSS 定位精通**:暫停確認你的理解:
+- ✅ 你能解釋為什麼植物需要絕對定位來實現拖放嗎?
+- ✅ 你了解相對容器如何創造定位上下文嗎?
+- ✅ 為什麼側邊容器使用絕對定位?
+- ✅ 如果完全移除定位聲明會發生什麼?
+
+**現實世界的聯繫**:想想 CSS 定位如何映射現實世界的佈局:
+- **Static**:書架上的書(自然排列)
+- **Relative**:稍微移動書本,但保持位置
+- **Absolute**:把書籤放在確切的頁數
+- **Fixed**:粘著便條紙,在翻頁時保持可見
+
+## 使用 CSS 建造生態瓶
+
+現在我們將只用 CSS 建造一個玻璃罐—不需要圖片或繪圖軟件。
+
+利用定位和透明度來創造逼真的玻璃、陰影與深度效果,展示CSS的視覺能力。此技術類似包豪斯運動建築師用簡單幾何形體創造複雜美麗建築。了解這些原則後,你將能認出許多網站設計背後的 CSS 技巧。
+
+```mermaid
+flowchart LR
+ A[罐蓋] --> E[完整生態瓶]
+ B[罐壁] --> E
+ C[泥土層] --> E
+ D[罐底] --> E
+ F[玻璃效果] --> E
+
+ A1["50% 寬度
5% 高度
頂部位置"] --> A
+ B1["60% 寬度
80% 高度
圓角
0.5 透明度"] --> B
+ C1["60% 寬度
5% 高度
深啡色
底層"] --> C
+ D1["50% 寬度
1% 高度
底部位置"] --> D
+ F1["細微陰影
透明度
Z 索引分層"] --> F
+
+ style E fill:#d1e1df,stroke:#3a241d
+ style A fill:#e8f5e8
+ style B fill:#e8f5e8
+ style C fill:#8B4513
+ style D fill:#e8f5e8
+```
+### 建造玻璃罐組件
-還值得注意的是 z-index 的使用,它控制元素的相對高度(使植物位於容器之上,看起來像是放在玻璃缸內)。
+讓我們逐一建造生態瓶罐的各部分。每個部分都使用絕對定位以及百分比大小以達到響應式設計:
-✅ 為什麼需要同時使用植物容器和植物的 CSS 選擇器?
+```css
+.jar-walls {
+ height: 80%;
+ width: 60%;
+ background: #d1e1df;
+ border-radius: 1rem;
+ position: absolute;
+ bottom: 0.5%;
+ left: 20%;
+ opacity: 0.5;
+ z-index: 1;
+ box-shadow: inset 0 0 2rem rgba(0, 0, 0, 0.1);
+}
-## CSS 定位
+.jar-top {
+ width: 50%;
+ height: 5%;
+ background: #d1e1df;
+ position: absolute;
+ bottom: 80.5%;
+ left: 25%;
+ opacity: 0.7;
+ z-index: 1;
+ border-radius: 0.5rem 0.5rem 0 0;
+}
-混合使用定位屬性(包括 static、relative、fixed、absolute 和 sticky 定位)可能有些棘手,但如果使用得當,可以很好地控制頁面上的元素。
+.jar-bottom {
+ width: 50%;
+ height: 1%;
+ background: #d1e1df;
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ opacity: 0.7;
+ border-radius: 0 0 0.5rem 0.5rem;
+}
+
+.dirt {
+ width: 60%;
+ height: 5%;
+ background: #3a241d;
+ position: absolute;
+ border-radius: 0 0 1rem 1rem;
+ bottom: 1%;
+ left: 20%;
+ opacity: 0.7;
+ z-index: -1;
+}
+```
-絕對定位的元素是相對於其最近的已定位祖先進行定位的,如果沒有已定位的祖先,則相對於文檔的 body 進行定位。
+**了解生態瓶的構造:**
+- **使用**百分比尺寸,實現在所有螢幕尺寸上的響應式縮放
+- **絕對定位**元素以精確堆疊和對齊
+- **應用**不同透明度值來創造玻璃的透光效果
+- **實施**`z-index`分層,讓植物看起來在罐子內部
+- **加入**微妙的盒陰影和圓角,讓外觀更真實
-相對定位的元素是根據 CSS 指定的方向,從其初始位置進行調整。
+### 使用百分比的響應式設計
-在我們的範例中,`plant-holder` 是一個相對定位的元素,位於一個絕對定位的容器內。這種行為的結果是,側邊欄容器被固定在左右兩側,而植物容器則嵌套在側邊欄內,調整自身位置以在側邊欄內垂直排列植物。
+注意所有尺寸都使用百分比,而非固定像素值:
-> 植物本身也使用了絕對定位,這是為了讓它可以被拖動,你會在下一課中了解更多。
+**為什麼這很重要:**
+- **確保**生態瓶在任意螢幕尺寸上按比例縮放
+- **維持**罐子組件之間的視覺關係
+- **提供**從手機到大螢幕桌面一致的體驗
+- **允許**設計適應變化,不破壞視覺佈局
-✅ 嘗試切換側邊容器和植物容器的定位類型。會發生什麼?
+### CSS 單位的運用
-## CSS 佈局
+我們使用 `rem` 單位為 border-radius 設定大小,這會相對於根字體大小縮放,創建更可及的設計,尊重使用者字體偏好。詳細可參考官方規範的 [CSS relative units](https://www.w3.org/TR/css-values-3/#font-relative-lengths)。
-現在,你將使用所學知識,完全通過 CSS 構建玻璃缸本身!
+✅ **視覺實驗**:嘗試修改這些值並觀察效果:
+- 將罐子透明度從 0.5 改為 0.8 — 玻璃外觀如何變化?
+- 調整污土顏色從 `#3a241d` 改為 `#8B4513` — 視覺影響是什麼?
+- 將污土的 `z-index` 改為 2 — 分層順序會怎樣?
-首先,使用 CSS 將 `.terrarium` div 的子元素設置為圓角矩形:
+### 🔄 **教學檢查點**
+**CSS 視覺設計理解**:確認你對視覺 CSS 的掌握:
+- ✅ 百分比尺寸如何創造響應式設計?
+- ✅ 為什麼透明度能營造玻璃透光效果?
+- ✅ `z-index` 在元素分層中扮演什麼角色?
+- ✅ border-radius 如何塑造罐子形狀?
-```CSS
-.jar-walls {
- height: 80%;
- width: 60%;
- background: #d1e1df;
- border-radius: 1rem;
- position: absolute;
- bottom: 0.5%;
- left: 20%;
- opacity: 0.5;
- z-index: 1;
-}
+**設計原則**:注意我們如何用簡單圖形構建複雜視覺:
+1. **矩形** → **圓角矩形** → **罐子組件**
+2. **純色** → **透明度** → **玻璃效果**
+3. **單一元素** → **分層組合** → **3D 外觀**
-.jar-top {
- width: 50%;
- height: 5%;
- background: #d1e1df;
- position: absolute;
- bottom: 80.5%;
- left: 25%;
- opacity: 0.7;
- z-index: 1;
-}
+---
-.jar-bottom {
- width: 50%;
- height: 1%;
- background: #d1e1df;
- position: absolute;
- bottom: 0%;
- left: 25%;
- opacity: 0.7;
-}
+## GitHub Copilot Agent 挑戰 🚀
-.dirt {
- width: 60%;
- height: 5%;
- background: #3a241d;
- position: absolute;
- border-radius: 0 0 1rem 1rem;
- bottom: 1%;
- left: 20%;
- opacity: 0.7;
- z-index: -1;
-}
-```
+使用 Agent 模式完成以下挑戰:
-注意這裡使用了百分比。如果縮小瀏覽器,你可以看到玻璃缸也會縮放。還要注意玻璃缸元素的寬度和高度百分比,以及每個元素如何絕對定位在中心,並固定在視窗底部。
+**說明:** 創建一個 CSS 動畫,讓生態瓶中的植物輕輕搖擺,模擬自然微風吹拂效果。這將幫助你練習 CSS 動畫、變形和關鍵影格,並提升生態瓶的視覺吸引力。
-我們還使用了 `rem` 作為圓角半徑的單位,這是一種相對於字體大小的長度。可以在 [CSS 規範](https://www.w3.org/TR/css-values-3/#font-relative-lengths) 中了解更多關於這種相對測量的方法。
+**提示:** 為 `.plant` 類添加 CSS 關鍵影格動畫,使植物輕輕左右擺動。創建一個擺動動畫,使每株植物沿水平方向旋轉約 2-3 度,持續時間 3-4 秒,且動畫無限循環,並使用平滑的緩動函數。
-✅ 嘗試更改玻璃缸的顏色和透明度與泥土的顏色和透明度。會發生什麼?為什麼?
+在這了解更多[Agent 模式](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode)。
----
+## 🚀 挑戰:加入玻璃反光效果
-## 🚀挑戰
+準備好用逼真的玻璃反光效果增強你的生態瓶了嗎?這技術將增加層次感與真實感。
-為玻璃缸的左下角添加一個“氣泡”光澤,使其看起來更像玻璃。你將為 `.jar-glossy-long` 和 `.jar-glossy-short` 添加樣式,使其看起來像反射的光澤。效果如下:
+你將創建細膩的高光,模擬光線如何在玻璃面反射。這類似文藝復興畫家 Jan van Eyck 利用光影與反射使繪畫中的玻璃呈現立體感。目標如下:
-
+
-要完成課後測驗,請參考此學習模組:[使用 CSS 為 HTML 應用程式設計樣式](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
+**你的挑戰:**
+- **創建**細膩的白色或淺色橢圓形,用於玻璃反光
+- **策略性定位**在罐子左側
+- **應用**適當透明度和模糊效果,模擬真實光反射
+- **使用**`border-radius` 創造自然泡泡狀形狀
+- **嘗試**漸層或盒陰影以增強真實感
## 課後測驗
[課後測驗](https://ff-quizzes.netlify.app/web/quiz/18)
-## 回顧與自學
+## 擴展你的 CSS 知識
+
+CSS 一開始可能會覺得複雜,但掌握這些核心概念將為進階技巧打下紮實基礎。
+
+**接下來的 CSS 學習領域:**
+- **Flexbox** - 簡化元素對齊和分佈
+- **CSS Grid** - 強大工具,建造複雜佈局
+- **CSS 變數** - 減少重複,提升維護性
+- **響應式設計** - 確保網站適用不同螢幕尺寸
+
+### 互動學習資源
+
+用這些有趣的實作遊戲練習概念:
+- 🐸 [Flexbox Froggy](https://flexboxfroggy.com/) - 通過挑戰精通 Flexbox
+- 🌱 [Grid Garden](https://codepip.com/games/grid-garden/) - 種胡蘿蔔學 CSS Grid
+- 🎯 [CSS Battle](https://cssbattle.dev/) - 編碼挑戰測試你的 CSS 技能
+
+### 額外學習
+
+欲獲得完整 CSS 基礎教學,完成這個 Microsoft Learn 課程:[使用 CSS 美化你的 HTML 應用程式](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
+
+### ⚡ **接下來 5 分鐘你可以做**
+- [ ] 開啟 DevTools,使用 Elements 面板檢查任一網站 CSS 樣式
+- [ ] 建立簡單 CSS 文件並連結至 HTML 頁面
+- [ ] 嘗試用不同方式改色:十六進位、RGB、命名顏色
+- [ ] 練習盒模型,為 div 加入 padding 和 margin
+
+### 🎯 **這小時你能完成的目標**
+- [ ] 完成課後測驗並複習 CSS 基礎
+- [ ] 用字型、顏色和間距美化你的 HTML 頁面
+- [ ] 使用 flexbox 或 grid 建立簡單佈局
+- [ ] 嘗試 CSS 過渡效果,實現流暢效果
+- [ ] 利用媒體查詢練習響應式設計
+
+### 📅 **你的 CSS 一週冒險**
+- [ ] 完成生態瓶樣式作業並加添創意
+- [ ] 精通 CSS Grid,打造相片集佈局
+- [ ] 學習 CSS 動畫讓設計生動起來
+- [ ] 探索 Sass 或 Less 等 CSS 預處理器
+- [ ] 研究設計原則並應用於 CSS
+- [ ] 分析並重現你在線看到的有趣設計
+
+### 🌟 **你的 CSS 一個月設計精通**
+- [ ] 建立完整響應式網站設計系統
+- [ ] 學習 CSS-in-JS 或類似 Tailwind 的功能型框架
+- [ ] 為開源專案貢獻 CSS 優化
+- [ ] 精通進階 CSS 概念,如客製屬性與內容隔離
+- [ ] 創建可重用的組件庫與模組化 CSS
+- [ ] 指導 CSS 初學者並分享設計心得
+
+## 🎯 你的 CSS 精通時間表
+
+```mermaid
+timeline
+ title CSS 學習進度
+
+ section 基礎 (10分鐘)
+ 檔案連結:將 CSS 連結到 HTML
+ :了解層疊規則
+ :學習繼承基礎
+
+ section 選擇器 (15分鐘)
+ 目標元素:元素選擇器
+ :類別模式
+ :ID 特異性
+ :組合器
+
+ section 盒模型 (20分鐘)
+ 版面基礎:外邊距與內邊距
+ :邊框屬性
+ :內容尺寸
+ :盒模型行為
+
+ section 定位 (25分鐘)
+ 元素位置:靜態與相對定位
+ :絕對定位
+ :Z 索引層次
+ :響應單位
+
+ section 視覺設計 (30分鐘)
+ 樣式掌握:顏色與透明度
+ :陰影與特效
+ :過渡效果
+ :變形屬性
+
+ section 響應式設計 (45分鐘)
+ 多裝置支援:媒體查詢
+ :彈性版面
+ :行動優先
+ :視口最佳化
+
+ section 進階技術 (1週)
+ 現代 CSS:Flexbox 版面
+ :CSS Grid 系統
+ :自訂屬性
+ :動畫關鍵影格
+
+ section 專業能力 (1個月)
+ CSS 架構:元件模式
+ :可維護程式碼
+ :效能優化
+ :跨瀏覽器相容性
+```
+### 🛠️ 你的 CSS 工具總結
+
+完成本課後,你已掌握:
+- **層疊理解**:樣式如何繼承與覆蓋
+- **選擇器精通**:準確鎖定元素、類別與 ID
+- **定位技巧**:策略性擺放與分層
+- **視覺設計**:創造玻璃效果、陰影與透明度
+- **響應式技術**:百分比佈局,適應任意螢幕
+- **代碼組織**:整潔且易維護的 CSS 結構
+- **現代實踐**:運用相對單位與可及設計模式
-CSS 看似簡單,但要為所有瀏覽器和螢幕尺寸完美設計應用程式樣式,仍然面臨許多挑戰。CSS-Grid 和 Flexbox 是為了讓這項工作更結構化、更可靠而開發的工具。通過玩 [Flexbox Froggy](https://flexboxfroggy.com/) 和 [Grid Garden](https://codepip.com/games/grid-garden/) 來學習這些工具。
+**下一步**:你的生態瓶已有結構(HTML)與樣式(CSS)。最後一課將用 JavaScript 加入互動!
## 作業
@@ -280,5 +729,7 @@ CSS 看似簡單,但要為所有瀏覽器和螢幕尺寸完美設計應用程
---
+
**免責聲明**:
-此文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。
\ No newline at end of file
+本文件由 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於追求準確性,請注意自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵資訊,建議聘請專業人工翻譯。因使用本翻譯所產生的任何誤解或誤譯,我們概不負責。
+
\ No newline at end of file
diff --git a/translations/hk/3-terrarium/2-intro-to-css/assignment.md b/translations/hk/3-terrarium/2-intro-to-css/assignment.md
index 0596e3020..10f5d2ad6 100644
--- a/translations/hk/3-terrarium/2-intro-to-css/assignment.md
+++ b/translations/hk/3-terrarium/2-intro-to-css/assignment.md
@@ -1,8 +1,8 @@
**免責聲明**:
-本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,請注意自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。
\ No newline at end of file
+本文件經由 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意自動翻譯結果可能包含錯誤或不準確之處。原始文件的母語版本應被視為具權威性的來源。對於重要資訊,建議採用專業人工翻譯。我們不對因使用此翻譯而產生的任何誤解或誤釋承擔責任。
+
\ No newline at end of file
diff --git a/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/README.md b/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/README.md
index 537e20e74..c6dcbc789 100644
--- a/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/README.md
+++ b/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/README.md
@@ -1,61 +1,205 @@
-# 玻璃花園項目第三部分:DOM 操作與閉包
+# Terrarium 項目第三部分:DOM 操作與 JavaScript 閉包
+
+```mermaid
+journey
+ title 你的 JavaScript DOM 之旅
+ section 基礎
+ 理解 DOM: 3: Student
+ 學習閉包: 4: Student
+ 連接元素: 4: Student
+ section 互動
+ 設置拖曳事件: 4: Student
+ 追蹤座標: 5: Student
+ 處理移動: 5: Student
+ section 精進
+ 新增清理功能: 4: Student
+ 測試功能: 5: Student
+ 完成生態箱: 5: Student
+```
+
+> Sketchnote 由 [Tomomi Imura](https://twitter.com/girlie_mac) 製作
+
+歡迎來到網頁開發中最吸引人的部分之一——讓事物互動起來!文件物件模型(DOM)就像你的 HTML 與 JavaScript 之間的橋樑,今天我們將利用它讓你的植物箱活起來。當 Tim Berners-Lee 發明第一台網頁瀏覽器時,他就想像了一個文件可以動態且互動的網路,而 DOM 讓這個願景成為可能。
+
+我們還會探索 JavaScript 閉包,這聽起來一開始可能會令人害怕。你可以把閉包想成創造「記憶口袋」,讓你的函數能記住重要資訊。就像你植物箱中的每棵植物各自擁有自己的資料記錄以追蹤位置一樣。在這課結束時,你會明白閉包是多麼自然且實用。
+
+我們要做的是這樣的:一個讓使用者可以將植物拖放到任意位置的植物箱。你將學會推動從拖放檔案上傳到互動遊戲的 DOM 操作技巧。讓我們來讓你的植物箱活起來。
+
+```mermaid
+mindmap
+ root((DOM & JavaScript))
+ DOM Tree
+ 元素選擇
+ 屬性存取
+ 事件處理
+ 動態更新
+ Events
+ 指標事件
+ 滑鼠事件
+ 觸控事件
+ 事件監聽器
+ Closures
+ 私有變數
+ 函數作用域
+ 記憶體持久化
+ 狀態管理
+ Drag & Drop
+ 位置追蹤
+ 坐標運算
+ 事件生命週期
+ 使用者互動
+ Modern Patterns
+ 事件委派
+ 效能
+ 跨裝置
+ 可達性
+```
+## 講課前測驗
+
+[講課前測驗](https://ff-quizzes.netlify.app/web/quiz/19)
+
+## 了解 DOM:你通往互動網頁的門戶
+
+文件物件模型(DOM)是 JavaScript 與 HTML 元素溝通的方式。當你的瀏覽器載入 HTML 頁面時,它會在記憶體中建立該頁面的結構化表示,那就是 DOM。可以把它想成一棵家譜樹,頁面中的每個 HTML 元素都是家族成員,而 JavaScript 可以存取、修改或重新排列他們。
+
+DOM 操作能將靜態網頁轉變成互動式網站。每次你看到按鈕在滑鼠懸停時改變顏色、內容在不重新載入頁面下更新或可以拖曳的元素,那就是 DOM 操作在運作。
+
+```mermaid
+flowchart TD
+ A["文件"] --> B["HTML"]
+ B --> C["標頭"]
+ B --> D["主體"]
+ C --> E["標題"]
+ C --> F["元標籤"]
+ D --> G["H1:我的生態瓶"]
+ D --> H["區塊:頁面容器"]
+ H --> I["區塊:左側容器"]
+ H --> J["區塊:右側容器"]
+ H --> K["區塊:生態瓶"]
+ I --> L["植物元素 1-7"]
+ J --> M["植物元素 8-14"]
+
+ L --> N["圖像#plant1"]
+ L --> O["圖像#plant2"]
+ M --> P["圖像#plant8"]
+ M --> Q["圖像#plant9"]
+
+ style A fill:#e1f5fe
+ style B fill:#f3e5f5
+ style D fill:#e8f5e8
+ style H fill:#fff3e0
+ style N fill:#ffebee
+ style O fill:#ffebee
+ style P fill:#ffebee
+ style Q fill:#ffebee
+```
+
+
+> DOM 與對應 HTML 標記的示意圖。來自 [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
+
+**以下使 DOM 強大的原因:**
+- **提供** 一種結構化方式存取頁面上的任何元素
+- **使得** 在不用重新整理的情況下動態更新內容成為可能
+- **允許** 即時對使用者互動如點擊與拖曳做出回應
+- **創造** 現代互動式網頁應用程式的基礎
+
+## JavaScript 閉包:創造有組織且強大的程式碼
+
+[JavaScript 閉包](https://developer.mozilla.org/docs/Web/JavaScript/Closures) 就像給函數自己的私人工作區,裡面有持續存在的記憶。想像達爾文在加拉巴哥群島上每種雀鳥根據環境發展出專門喙的故事——閉包也是類似,創造專門的函數,使其「記得」特定上下文,即使父函數已經完成執行。
+
+在我們的植物箱中,閉包讓每棵植物能獨立記住自己的位置。這種模式在專業 JavaScript 開發中到處可見,是個非常寶貴的概念。
+
+```mermaid
+flowchart LR
+ A["dragElement(plant1)"] --> B["建立閉包"]
+ A2["dragElement(plant2)"] --> B2["建立閉包"]
+
+ B --> C["私有變數"]
+ B2 --> C2["私有變數"]
+
+ C --> D["pos1, pos2, pos3, pos4"]
+ C --> E["pointerDrag 函數"]
+ C --> F["elementDrag 函數"]
+ C --> G["stopElementDrag 函數"]
+
+ C2 --> D2["pos1, pos2, pos3, pos4"]
+ C2 --> E2["pointerDrag 函數"]
+ C2 --> F2["elementDrag 函數"]
+ C2 --> G2["stopElementDrag 函數"]
+
+ H["植物 1 記住它的位置"] --> B
+ H2["植物 2 記住它的位置"] --> B2
+
+ style B fill:#e8f5e8
+ style B2 fill:#e8f5e8
+ style C fill:#fff3e0
+ style C2 fill:#fff3e0
+```
+> 💡 **理解閉包**:閉包是 JavaScript 中一個重要主題,許多開發者使用多年後才完全掌握所有理論面。今天我們主要探討實務應用——你會自然看到閉包在我們建構互動功能時出現。當你看到它們如何解決實際問題,理解就會逐漸形成。
-
-> [Tomomi Imura](https://twitter.com/girlie_mac) 的手繪筆記
+
-## 課前測驗
+> DOM 與對應 HTML 標記的示意圖。來自 [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
-[課前測驗](https://ff-quizzes.netlify.app/web/quiz/19)
+在本課中,我們將完成互動植物箱專案,寫出 JavaScript 讓使用者能操控頁面上的植物。
-### 簡介
+## 開始之前:為成功做準備
-操作 DOM(文件物件模型)是網頁開發中的一個關鍵部分。根據 [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) 的定義:「文件物件模型 (DOM) 是一種數據表示形式,用於描述構成網頁結構和內容的物件。」由於操作 DOM 的挑戰,許多開發者選擇使用 JavaScript 框架來取代原生 JavaScript 進行 DOM 管理,但我們這次將嘗試自己動手完成!
+你需要之前植物箱課程的 HTML 與 CSS 檔案——我們即將把靜態設計變成交互式。如果你是第一次加入,先完成那些課程會有重要的背景知識。
-此外,本課程還會介紹 [JavaScript 閉包](https://developer.mozilla.org/docs/Web/JavaScript/Closures) 的概念。閉包可以理解為一個函數包裹著另一個函數,使內部函數能夠訪問外部函數的作用域。
+以下是我們要做的事:
+- **為所有植物實現流暢的拖放功能**
+- **追蹤座標,讓植物記住自己的位置**
+- **建立完整的互動介面,使用純 JavaScript**
+- **用閉包模式寫出乾淨、有組織的程式碼**
-> JavaScript 閉包是一個廣泛且複雜的主題。本課程僅涉及最基本的概念。在這個玻璃花園的代碼中,你會發現一個閉包:一個內部函數和一個外部函數的結構設計,使內部函數能夠訪問外部函數的作用域。若想深入了解其運作方式,請參考 [詳細文檔](https://developer.mozilla.org/docs/Web/JavaScript/Closures)。
+## 設定你的 JavaScript 檔案
-我們將使用閉包來操作 DOM。
+讓我們開始建立讓你的植物箱互動的 JavaScript 檔案。
-可以將 DOM 想像成一棵樹,代表了網頁文件可以被操作的所有方式。各種 API(應用程式介面)被設計出來,讓開發者可以使用自己選擇的程式語言來訪問 DOM,並進行編輯、修改、重組或其他管理操作。
+**步驟 1:建立你的程式檔**
-
+在你的植物箱資料夾中,建立一個新檔案命名為 `script.js`。
-> DOM 與其對應的 HTML 標記的表示圖。來源:[Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
+**步驟 2:將 JavaScript 連結到你的 HTML**
-在本課程中,我們將完成互動式玻璃花園項目,通過編寫 JavaScript 代碼,讓用戶能夠操作頁面上的植物。
+在你的 `index.html` 的 `` 區塊加入這個 script 標籤:
-### 前置條件
+```html
+
+```
-你應該已經完成了玻璃花園的 HTML 和 CSS 部分。在本課程結束時,你將能夠通過拖拽將植物移入或移出玻璃花園。
+**`defer` 屬性的重要性:**
+- **確保** JavaScript 等待所有 HTML 載入完成後才執行
+- **避免** JavaScript 在元素尚未準備好時尋找它們而造成錯誤
+- **保證** 所有植物元素都可被互動使用
+- **比把 script 放到頁面底部有更好的效能**
-### 任務
+> ⚠️ **重要提醒**:`defer` 屬性可以避免常見的時序問題。沒有它,JavaScript 可能嘗試存取還沒載入的 HTML 元素,導致錯誤。
-在你的玻璃花園資料夾中,創建一個名為 `script.js` 的新文件,並在 `` 區域中引入該文件:
+---
-```html
-
-```
+## 將 JavaScript 與 HTML 元素連結
-> 注意:在將外部 JavaScript 文件引入 HTML 文件時,使用 `defer` 屬性,這樣可以確保 JavaScript 在 HTML 文件完全加載後才執行。你也可以使用 `async` 屬性,允許腳本在 HTML 文件解析時執行,但在我們的情況下,確保 HTML 元素完全可用以進行拖拽操作更為重要。
----
+在讓元素可拖放前,JavaScript 需要找到它們,在 DOM 中定位它們。可以把這看成圖書館的目錄系統——只要有目錄號碼,你就能準確找到想要的書。
-## DOM 元素
+我們會使用 `document.getElementById()` 來建立這連結。這就像有一個精確的檔案系統——你給出 ID,它就能找到你 HTML 中的正確元素。
-首先,你需要在 DOM 中創建對要操作的元素的引用。在我們的例子中,這些元素是目前位於側邊欄的 14 個植物。
+### 讓所有植物都能拖曳
-### 任務
+在你的 `script.js` 檔案加入以下程式碼:
-```html
+```javascript
+// 啟用所有14種植物的拖曳功能
dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
@@ -72,159 +216,556 @@ dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));
```
-這裡發生了什麼?你正在引用文件,並在其 DOM 中查找具有特定 Id 的元素。還記得我們在 HTML 課程中為每個植物圖片分配了唯一的 Id(例如 `id="plant1"`)嗎?現在你可以利用這些 Id。識別每個元素後,你將該元素傳遞給一個名為 `dragElement` 的函數(稍後會構建該函數)。因此,HTML 中的元素現在已啟用拖拽功能,或者即將啟用。
+**這段程式碼完成了什麼:**
+- **定位** 每個植物元素於 DOM 中,根據其獨特的 ID
+- **取得** JavaScript 對應的 HTML 元素參考
+- **將** 每個元素傳遞給 `dragElement` 函數(接下來我們會寫)
+- **準備** 每棵植物成為可拖放物件
+- **橋接** 你的 HTML 結構與 JavaScript 功能
+
+> 🎯 **為什麼用 ID 而不用 Class?** ID 是專屬於特定元素的唯一識別碼,而 CSS 的類別(class)主要是用來對多個元素做樣式設定。當 JavaScript 需要操作單一元素時,ID 提供了精確且效能佳的方式。
+
+> 💡 **小貼士**:注意我們對每棵植物都呼叫了 `dragElement()` 一次。這確保每棵植物都有獨立的拖曳行為,這對流暢的使用體驗很重要。
+
+### 🔄 **教學回顧檢查**
+**DOM 連結理解**:在進入拖曳功能前,確認你理解:
+- ✅ 如何用 `document.getElementById()` 定位 HTML 元素
+- ✅ 為什麼我們為每棵植物使用獨特的 ID
+- ✅ script 標籤中 `defer` 屬性的目的
+- ✅ JavaScript 與 HTML 透過 DOM 如何互相連接
-✅ 為什麼我們通過 Id 引用元素?為什麼不通過它們的 CSS 類名?你可以回顧之前的 CSS 課程來回答這個問題。
+**自我測試**:如果兩個元素有相同 ID,會發生什麼事?為什麼 `getElementById()` 只回傳一個元素?
+*答案:ID 應該唯一;如果重複,只有第一個元素會被找到*
---
-## 閉包
+## 建立拖曳元素的閉包函數
-現在你可以創建 `dragElement` 閉包了,這是一個外部函數,包裹著一個或多個內部函數(在我們的例子中是三個)。
+現在我們來打造拖曳功能的核心:一個閉包,用來管理每棵植物的拖曳行為。這閉包包含多個內部函數,協同追蹤滑鼠移動並更新元素位置。
-當一個或多個函數需要訪問外部函數的作用域時,閉包非常有用。以下是一個例子:
+閉包很適合這項任務,因為它能讓我們創造「私有」變數,在函數調用間持續存在,給每棵植物獨立的座標追蹤系統。
+
+### 用簡單範例理解閉包
+
+讓我用一個簡單範例說明閉包的概念:
```javascript
-function displayCandy(){
- let candy = ['jellybeans'];
- function addCandy(candyType) {
- candy.push(candyType)
- }
- addCandy('gumdrops');
+function createCounter() {
+ let count = 0; // 這就像一個私有變量
+
+ function increment() {
+ count++; // 內部函數會記住外部變量
+ return count;
+ }
+
+ return increment; // 我們將內部函數返回
}
-displayCandy();
-console.log(candy)
-```
-
-在這個例子中,`displayCandy` 函數包裹了一個函數,該函數將新的糖果類型推入已存在於函數中的數組。如果你運行這段代碼,`candy` 數組將是未定義的,因為它是一個局部變數(僅限於閉包的作用域)。
-✅ 如何讓 `candy` 數組可訪問?嘗試將其移到閉包之外。這樣,數組將變為全域變數,而不是僅限於閉包的局部作用域。
+const myCounter = createCounter();
+console.log(myCounter()); // 1
+console.log(myCounter()); // 2
+```
-### 任務
+**這個閉包模式做了什麼:**
+- **建立** 一個私有的 `count` 變數,只存在於此閉包中
+- **內部函數** 可以存取並修改外部變數(這就是閉包機制)
+- **我們回傳內部函數時**,它會保留與那份私有資料的連結
+- **即使 `createCounter()` 執行完後**,`count` 依然存在並記得它的值
+
+### 閉包為什麼特別適合拖曳功能
+
+對我們的植物箱來說,每棵植物需要記住目前的位置座標。閉包提供了完美解決方案:
+
+**專案的主要好處:**
+- **獨立維持** 每棵植物私有的位置變數
+- **保留** 拖曳事件間的座標數據
+- **避免** 不同可拖曳元素間的變數衝突
+- **創造** 乾淨且有組織的程式碼結構
+
+> 🎯 **學習目標**:你現在不需要完全精通閉包。專注於看出它們如何幫我們整理程式碼、維持拖曳功能狀態。
+
+```mermaid
+stateDiagram-v2
+ [*] --> Ready: 頁面加載
+ Ready --> DragStart: 使用者按下 (pointerdown)
+ DragStart --> Dragging: 鼠標/手指移動 (pointermove)
+ Dragging --> Dragging: 繼續移動
+ Dragging --> DragEnd: 使用者放開 (pointerup)
+ DragEnd --> Ready: 重設以便下一次拖曳
+
+ state DragStart {
+ [*] --> CapturePosition
+ CapturePosition --> SetupListeners
+ SetupListeners --> [*]
+ }
+
+ state Dragging {
+ [*] --> CalculateMovement
+ CalculateMovement --> UpdatePosition
+ UpdatePosition --> [*]
+ }
+
+ state DragEnd {
+ [*] --> RemoveListeners
+ RemoveListeners --> CleanupState
+ CleanupState --> [*]
+ }
+```
+### 建立 dragElement 函數
-在 `script.js` 中的元素聲明下,創建一個函數:
+現在我們寫出控制拖曳邏輯的主要函數。把它加入你聲明植物元素的程式碼下面:
```javascript
function dragElement(terrariumElement) {
- //set 4 positions for positioning on the screen
- let pos1 = 0,
- pos2 = 0,
- pos3 = 0,
- pos4 = 0;
- terrariumElement.onpointerdown = pointerDrag;
+ // 初始化位置追蹤變數
+ let pos1 = 0, // 之前的滑鼠 X 位置
+ pos2 = 0, // 之前的滑鼠 Y 位置
+ pos3 = 0, // 目前的滑鼠 X 位置
+ pos4 = 0; // 目前的滑鼠 Y 位置
+
+ // 設定初始拖曳事件監聽器
+ terrariumElement.onpointerdown = pointerDrag;
}
```
-`dragElement` 從腳本頂部的聲明中獲取其 `terrariumElement` 對象。然後,你為傳遞到函數的對象設置了一些初始位置,這些位置的值為 `0`。這些是局部變數,將在閉包內為每個元素添加拖拽功能時進行操作。玻璃花園將通過這些被拖拽的元素填充,因此應用程序需要跟蹤它們的放置位置。
-
-此外,傳遞給該函數的 `terrariumElement` 被分配了一個 `pointerdown` 事件,這是 [web API](https://developer.mozilla.org/docs/Web/API) 的一部分,旨在幫助管理 DOM。`onpointerdown` 事件在按下按鈕時觸發,或者在我們的例子中,當觸摸一個可拖拽的元素時觸發。該事件處理程序適用於 [網頁和移動瀏覽器](https://caniuse.com/?search=onpointerdown),但有少數例外。
-
-✅ [事件處理程序 `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) 在跨瀏覽器支持方面更廣泛;為什麼這裡不使用它?想一想你希望創建的屏幕交互的具體類型。
+**位置追蹤系統解說:**
+- **`pos1` 和 `pos2`**:儲存舊滑鼠位置和新滑鼠位置之間的差距
+- **`pos3` 和 `pos4`**:追蹤滑鼠目前的座標
+- **`terrariumElement`**:我們正在改造成可拖曳的那個植物元素
+- **`onpointerdown`**:使用者開始拖曳時觸發的事件
+
+**閉包模式運作方式:**
+- **為每個植物元素建立** 私有位置變數
+- **在拖曳過程中維持** 這些變數
+- **確保** 每棵植物獨立追蹤自己的座標
+- **透過 `dragElement` 函數提供** 乾淨的介面
+
+### 為什麼使用 pointer 事件?
+
+你可能會想,為什麼我們用 `onpointerdown` 而不是較常見的 `onclick`。原因如下:
+
+| 事件類型 | 適用情境 | 注意事項 |
+|------------|----------|-------------|
+| `onclick` | 簡單按鈕點擊 | 只能處理點擊與放開,無法拖曳 |
+| `onpointerdown` | 滑鼠和觸控都適用 | 新穎且目前廣泛支援 |
+| `onmousedown` | 只適用桌面滑鼠 | 忽略行動裝置使用者 |
+
+**為什麼 pointer 事件很適合我們的需求:**
+- **不論是滑鼠、手指或觸控筆** 都能正常運作
+- **無論用筆電、平板或手機都一樣流暢**
+- **能處理真正的拖曳動作,而非只是點擊放開**
+- **帶來使用者期望的順暢體驗**
+
+> 💡 **未來趨勢**:Pointer 事件是最新的使用者互動標準。比起寫分開的滑鼠與觸控程式碼,這種方式同時涵蓋兩者。非常酷對吧?
+
+### 🔄 **教學回顧檢查**
+**事件處理理解**:暫停確認你掌握:
+- ✅ 為何用 pointer 事件而非 mouse 事件?
+- ✅ 閉包變數如何在函數調用間持續存在?
+- ✅ `preventDefault()` 在流暢拖曳中扮演什麼角色?
+- ✅ 為什麼事件監聽器是綁在文件(document)而不是各個元素上?
+
+**與現實連結**:想想你每天使用過的拖放介面:
+- **檔案上傳**:將檔案拖到瀏覽器視窗
+- **看板任務板**:任務在欄目間移動
+- **圖片集**:重新排列照片順序
+- **行動介面**:觸控螢幕上的滑動與拖曳
---
-## Pointerdrag 函數
+## pointerDrag 函數:捕捉拖曳的開始
-`terrariumElement` 現在已準備好被拖拽;當觸發 `onpointerdown` 事件時,函數 `pointerDrag` 被調用。在這行代碼下方添加該函數:`terrariumElement.onpointerdown = pointerDrag;`:
+當使用者按下植物(不論是滑鼠點擊或手指觸控),`pointerDrag` 函數就會啟動。它會存下初始座標並準備拖曳系統。
-### 任務
+把這個函數加到你的 `dragElement` 閉包裡,緊接在 `terrariumElement.onpointerdown = pointerDrag;` 這行後面:
```javascript
function pointerDrag(e) {
- e.preventDefault();
- console.log(e);
- pos3 = e.clientX;
- pos4 = e.clientY;
+ // 阻止瀏覽器預設行為(例如文字選取)
+ e.preventDefault();
+
+ // 捕捉初始鼠標/觸摸位置
+ pos3 = e.clientX; // 拖曳開始的 X 座標
+ pos4 = e.clientY; // 拖曳開始的 Y 座標
+
+ // 設置拖曳過程的事件監聽器
+ document.onpointermove = elementDrag;
+ document.onpointerup = stopElementDrag;
}
```
-這裡發生了幾件事。首先,你使用 `e.preventDefault();` 阻止了 `pointerdown` 事件的默認行為。這樣你可以更好地控制界面的行為。
+**逐步解說:**
+- **防止** 瀏覽器的預設行為,以免干擾拖曳
+- **記錄** 使用者開始拖曳時的確切座標
+- **建立** 對持續拖曳移動的事件監聽器
+- **準備** 追蹤整個文件中的滑鼠或手指動作
-> 當你完全構建腳本文件後,回到這行代碼並嘗試刪除 `e.preventDefault()` - 會發生什麼?
+### 理解事件預防
-其次,在瀏覽器窗口中打開 `index.html`,並檢查界面。當你點擊一個植物時,你可以看到如何捕獲 'e' 事件。深入查看該事件,看看一次 `pointerdown` 事件收集了多少信息!
+`e.preventDefault()` 這行對順暢拖曳至關重要:
-接下來,注意如何將局部變數 `pos3` 和 `pos4` 設置為 `e.clientX`。你可以在檢查面板中找到 `e` 的值。這些值捕獲了你點擊或觸摸植物時的 x 和 y 坐標。由於你需要對植物的拖拽行為進行精細控制,因此需要跟蹤它們的坐標。
+**若不防止,瀏覽器可能會:**
+- **選取** 用戶拖曳時劃過的文字
+- **觸發** 右鍵拖曳時的選單
+- **干擾** 我們自訂的拖曳功能
+- **造成** 拖動過程中的視覺異常
-✅ 現在是否更清楚為什麼整個應用程序是用一個大的閉包構建的?如果不是閉包,你將如何為 14 個可拖拽的植物維持作用域?
+> 🔍 **實驗**:完成本課後,試著移除 `e.preventDefault()`,觀察拖曳體驗如何改變。你會很快知道這行為什麼必要!
-完成初始函數,通過在 `pos4 = e.clientY` 下添加另外兩個指針事件操作:
+### 座標追蹤系統
-```html
+`e.clientX` 和 `e.clientY` 屬性給出滑鼠/觸控點的精確座標:
+
+| 屬性 | 量測項目 | 使用案例 |
+|----------|------------------|----------|
+| `clientX` | 相對於視窗的水平位置 | 追蹤左右移動 |
+| `clientY` | 相對於視窗的垂直位置 | 追蹤上下移動 |
+**了解這些座標:**
+- **提供** 像素級精確的定位資訊
+- **隨使用者移動指標** 實時更新
+- **跨不同螢幕尺寸和縮放等級** 保持一致
+- **啟用** 平滑、響應式的拖放互動
+
+### 設置文件級事件監聽器
+
+注意我們如何將移動和停止事件附加在整個 `document` 上,而不僅是植物元素:
+
+```javascript
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
-現在你正在指示植物隨著指針移動而被拖拽,並在取消選擇植物時停止拖拽。`onpointermove` 和 `onpointerup` 都是與 `onpointerdown` 相同 API 的一部分。由於你尚未定義 `elementDrag` 和 `stopElementDrag` 函數,界面現在會拋出錯誤,因此接下來構建這些函數。
-## elementDrag 和 stopElementDrag 函數
+**為何附加到 document:**
+- **即使滑鼠離開植物元素也能繼續追蹤**
+- **防止使用者快速移動時拖動中斷**
+- **在整個螢幕上提供平滑拖動體驗**
+- **處理游標移出瀏覽器視窗的邊界情況**
-你將通過添加另外兩個內部函數來完成閉包,這些函數將處理拖拽植物和停止拖拽時的行為。你希望的行為是,隨時可以拖拽任何植物,並將其放置在屏幕上的任何位置。這個界面非常靈活(例如,沒有特定的放置區域),讓你可以自由設計自己的玻璃花園,添加、移除和重新定位植物。
+> ⚡ **效能提示**:拖動停止時,我們會清理這些文件級監聽器,避免記憶體洩漏和效能問題。
-### 任務
+## 完善拖曳系統:移動與清理
-在 `pointerDrag` 的閉合大括號後添加 `elementDrag` 函數:
+現在我們將新增兩個處理實際拖曳移動和拖曳停止時清理的函式。這些函式協同工作,為你的植物造景提供平滑、響應式的移動功能。
+
+### elementDrag 函式:追蹤移動
+
+在 `pointerDrag` 的結束花括號後面添加 `elementDrag` 函式:
```javascript
function elementDrag(e) {
- pos1 = pos3 - e.clientX;
- pos2 = pos4 - e.clientY;
- pos3 = e.clientX;
- pos4 = e.clientY;
- console.log(pos1, pos2, pos3, pos4);
- terrariumElement.style.top = terrariumElement.offsetTop - pos2 + 'px';
- terrariumElement.style.left = terrariumElement.offsetLeft - pos1 + 'px';
+ // 計算自上次事件以來移動的距離
+ pos1 = pos3 - e.clientX; // 水平移動距離
+ pos2 = pos4 - e.clientY; // 垂直移動距離
+
+ // 更新當前位置追蹤
+ pos3 = e.clientX; // 新的當前 X 位置
+ pos4 = e.clientY; // 新的當前 Y 位置
+
+ // 將移動應用至元素的位置
+ terrariumElement.style.top = (terrariumElement.offsetTop - pos2) + 'px';
+ terrariumElement.style.left = (terrariumElement.offsetLeft - pos1) + 'px';
}
```
-在這個函數中,你對之前在外部函數中設置的初始位置 1-4 進行了大量操作。這裡發生了什麼?
-
-當你拖拽時,你通過將 `pos3`(之前設置為 `e.clientX`)減去當前的 `e.clientX` 值來重新分配 `pos1`。對 `pos2` 進行了類似的操作。然後,你將 `pos3` 和 `pos4` 重置為元素的新 X 和 Y 坐標。你可以在拖拽時在控制台中觀察這些變化。接著,你操作植物的 CSS 樣式,根據這些新位置計算植物的頂部和左側 X 和 Y 坐標,並設置其新位置。
-
-> `offsetTop` 和 `offsetLeft` 是 CSS 屬性,用於根據父元素設置元素的位置;其父元素可以是任何非 `static` 定位的元素。
-所有這些位置的重新計算使你能夠微調玻璃花園及其植物的行為。
-
-### 任務
+**理解座標數學運算:**
+- **`pos1` 和 `pos2`**:計算滑鼠自上次更新以來移動的距離
+- **`pos3` 和 `pos4`**:儲存當前滑鼠位置供下次計算使用
+- **`offsetTop` 和 `offsetLeft`**:獲取元素當前在頁面上的位置
+- **減法邏輯**:將元素移動與滑鼠移動距離同步
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant Mouse
+ participant JavaScript
+ participant Plant
+
+ User->>Mouse: 在 (100, 50) 開始拖曳
+ Mouse->>JavaScript: pointerdown 事件
+ JavaScript->>JavaScript: 儲存初始位置 (pos3=100, pos4=50)
+ JavaScript->>JavaScript: 設置移動/鬆開偵聽器
+
+ User->>Mouse: 移動至 (110, 60)
+ Mouse->>JavaScript: pointermove 事件
+ JavaScript->>JavaScript: 計算: pos1=10, pos2=10
+ JavaScript->>Plant: 更新: left += 10px, top += 10px
+ Plant->>Plant: 在新位置渲染
+
+ User->>Mouse: 在 (120, 65) 放開
+ Mouse->>JavaScript: pointerup 事件
+ JavaScript->>JavaScript: 移除偵聽器
+ JavaScript->>JavaScript: 重設以供下次拖曳
+```
+**移動計算解析:**
+1. **測量** 新舊滑鼠位置差異
+2. **計算** 根據滑鼠移動決定元素移動距離
+3. **即時更新** 元素的 CSS 位置屬性
+4. **儲存** 新位置作為下一次計算基準
+
+### 數學的視覺化表示
+
+```mermaid
+sequenceDiagram
+ participant Mouse
+ participant JavaScript
+ participant Plant
+
+ Mouse->>JavaScript: 從 (100,50) 移動到 (110,60)
+ JavaScript->>JavaScript: 計算:向右移動 10px,向下移動 10px
+ JavaScript->>Plant: 位置更新:向右 +10px,向下 +10px
+ Plant->>Plant: 在新位置渲染
+```
+### stopElementDrag 函式:清理工作
-完成界面的最後一步是在 `elementDrag` 的閉合大括號後添加 `stopElementDrag` 函數:
+在 `elementDrag` 的結束花括號後添加此清理函式:
```javascript
function stopElementDrag() {
- document.onpointerup = null;
- document.onpointermove = null;
+ // 移除文件層級的事件監聽器
+ document.onpointerup = null;
+ document.onpointermove = null;
}
```
-這個小函數重置了 `onpointerup` 和 `onpointermove` 事件,這樣你可以重新開始拖拽植物,或者開始拖拽新的植物。
+**清理為何重要:**
+- **防止因殘留事件監聽器導致的記憶體洩漏**
+- **使用者釋放植物後停止拖曳行為**
+- **允許其他元素獨立拖動**
+- **重設系統以便下一次拖曳操作**
+
+**未清理會發生什麼:**
+- 事件監聽器在拖曳停止後仍持續執行
+- 累積未使用的監聽器導致效能下降
+- 與其他元素互動時產生意外行為
+- 瀏覽器資源浪費於不必要的事件處理
+
+### 理解 CSS 位置屬性
+
+我們的拖動系統操作兩個關鍵 CSS 屬性:
+
+| 屬性 | 控制內容 | 我們如何使用 |
+|------|----------|--------------|
+| `top` | 距離頂部邊緣的距離 | 拖動過程中的垂直定位 |
+| `left` | 距離左側邊緣的距離 | 拖動過程中的水平定位 |
+
+**關於 offset 屬性的重要觀察:**
+- **`offsetTop`**:距離已定位祖先元素頂部的當前距離
+- **`offsetLeft`**:距離已定位祖先元素左側的當前距離
+- **定位上下文**:這些值相對於最近的已定位祖先元素
+- **即時更新**:當修改 CSS 屬性時立即變動
+
+> 🎯 **設計理念**:此拖曳系統刻意保持彈性—沒有「放置區域」或其他限制。用戶可自由將植物放置於任意位置,完全掌控自己的造景設計。
+
+## 綜合整合:完整拖曳系統
-✅ 如果你不將這些事件設置為 null,會發生什麼?
+恭喜!你剛完成了一個用純 JavaScript 製作的高級拖放系統。你的完整 `dragElement` 函式內含一個功能強大的閉包,管理著:
-現在你已經完成了你的項目!
+**你的閉包達成的功能:**
+- **獨立維護** 每個植物的私有位置變數
+- **處理** 從開始拖曳到結束的整個生命週期
+- **提供** 跨整個螢幕的平滑、響應式移動
+- **妥善清理** 資源以預防記憶體洩漏
+- **創造** 直覺且具創造力的造景介面
-🥇恭喜!你已經完成了你的美麗玻璃花園!
+### 測試你的互動式植物瓶景觀
+
+現在測試你的互動式植物瓶景觀!在瀏覽器中打開你的 `index.html` 並嘗試操作:
+
+1. **點擊並按住** 任一植物開始拖曳
+2. **移動滑鼠或手指** 看著植物平滑跟隨
+3. **放開** 以將植物放置在新位置
+4. **嘗試** 不同的排列方式探索介面
+
+🥇 **成就感**:你已創建一個完全互動的網頁應用,掌握專業開發者每天使用的核心概念。這拖放功能底層原理同時支撐著檔案上傳、看板列表及各種互動介面。
+
+### 🔄 **教學檢視點**
+**完整系統理解**:檢驗你對拖曳系統的掌握:
+- ✅ 閉包如何維護每個植物的獨立狀態?
+- ✅ 為什麼座標計算的數學對平滑移動必要?
+- ✅ 忘記清理事件監聽器會導致什麼?
+- ✅ 這種模式如何擴展到更複雜的互動?
+
+**程式碼品質反思**:回顧完整方案:
+- **模組化設計**:每個植物獲得自己的閉包實例
+- **事件效能**:妥善設定與清理監聽器
+- **跨裝置支援**:適用桌面與行動裝置
+- **效能意識**:無記憶體洩漏或多餘計算
+
+
---
-## 🚀挑戰
+## GitHub Copilot Agent 挑戰 🚀
+
+使用 Agent 模式完成以下挑戰:
-為你的閉包添加新的事件處理程序,讓植物能夠執行更多操作;例如,雙擊植物將其置於最前方。發揮創意吧!
+**描述:** 擴充植物瓶專案,新增重設功能,讓所有植物能夠平滑動畫回復原始位置。
+
+**提示:** 創建一個重設按鈕,點擊後會使用 CSS 過渡動畫將所有植物平滑回復原側欄的原始位置。函式應在頁面載入時儲存原始位置,按下重設按鈕時以 1 秒動畫平滑回復。
+
+了解更多關於 [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) 的資訊。
+
+## 🚀 額外挑戰:擴展你的技能
+
+準備好將植物瓶昇華到下一層嗎?試試以下擴充功能:
+
+**創意延伸:**
+- **雙擊** 植物將其置頂(z-index 操作)
+- **加入視覺反饋**,如滑鼠懸停時植物微光效果
+- **實作邊界限制**,避免將植物拖出植物瓶範圍
+- **創建儲存功能**,利用 localStorage 記錄植物位置
+- **加入音效**,在拾取與放置植物時播放聲音
+
+> 💡 **學習機會**:這些挑戰將教你更多 DOM 操控、事件處理及用戶體驗設計技巧。
## 課後測驗
[課後測驗](https://ff-quizzes.netlify.app/web/quiz/20)
-## 複習與自學
+## 複習與自學:深化理解
+
+你已掌握 DOM 操控和閉包的基本,還有更多可學!以下是擴展知識和技能的路徑。
+
+### 替代的拖放實作方法
+
+我們使用了指標事件以獲得最大彈性,但網頁開發還有其他方法:
+
+| 方法 | 適合用例 | 學習價值 |
+|------|----------|----------|
+| [HTML 拖放 API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | 檔案上傳、正式拖放區域 | 了解瀏覽器原生能力 |
+| [Touch 事件](https://developer.mozilla.org/docs/Web/API/Touch_events) | 行動裝置特定互動 | 行動優先開發模式 |
+| CSS `transform` 屬性 | 平滑動畫 | 效能最佳化技巧 |
+
+### 進階 DOM 操作主題
+
+**下一步學習重點:**
+- **事件委託**:高效處理多個元素事件
+- **交叉觀察器 (Intersection Observer)**:偵測元素進出視窗
+- **變動觀察器 (Mutation Observer)**:監控 DOM 結構變化
+- **網頁元件 (Web Components)**:創建可重用封裝 UI 元素
+- **虛擬 DOM 概念**:了解框架如何優化 DOM 更新
+
+### 持續學習的必要資源
+
+**技術文件:**
+- [MDN 指標事件指南](https://developer.mozilla.org/docs/Web/API/Pointer_events) - 完整指標事件參考
+- [W3C 指標事件規範](https://www.w3.org/TR/pointerevents1/) - 官方標準文件
+- [JavaScript 閉包深度解析](https://developer.mozilla.org/docs/Web/JavaScript/Closures) - 進階閉包範例
+
+**瀏覽器相容性:**
+- [CanIUse.com](https://caniuse.com/) - 檢查跨瀏覽器功能支援
+- [MDN 瀏覽器兼容性資料](https://github.com/mdn/browser-compat-data) - 詳細支援資料
+
+**練習機會:**
+- **構建** 拼圖遊戲,使用類似拖曳機制
+- **製作** 看板列表,拖放任務管理
+- **設計** 可拖動的圖片集
+- **嘗試** 移動裝置手勢互動開發
+
+> 🎯 **學習策略**:最好的鞏固方式就是實作。試著建立不同拖曳介面,每個專案都能教你更多關於用戶互動和 DOM 操控。
+
+### ⚡ **接下來 5 分鐘的事**
+- [ ] 開啟瀏覽器開發者工具,在控制台輸入 `document.querySelector('body')`
+- [ ] 嘗試使用 `innerHTML` 或 `textContent` 變更網頁文字
+- [ ] 為網頁中任一按鈕或連結添加點擊事件監聽
+- [ ] 使用元素面板檢查 DOM 樹結構
+
+### 🎯 **本小時可達成目標**
+- [ ] 完成課後測驗並回顧 DOM 操作概念
+- [ ] 創建一個回應使用者點擊的互動網頁
+- [ ] 練習各類事件處理(click、mouseover、keypress)
+- [ ] 製作簡易待辦清單或計數器,使用 DOM 操控
+- [ ] 探索 HTML 元素與 JavaScript 物件的關係
+
+### 📅 **一週的 JavaScript 旅程**
+- [ ] 完成帶拖放功能的互動植物瓶專案
+- [ ] 掌握事件委託以提升事件處理效率
+- [ ] 學習事件循環與非同步 JavaScript
+- [ ] 透過建立模組練習閉包私有狀態
+- [ ] 探索現代 DOM API,如交叉觀察器
+- [ ] 製作互動元件,無需框架
+
+### 🌟 **一個月的 JavaScript 精通**
+- [ ] 建立複雜單頁應用,使用純 JavaScript
+- [ ] 學習並比較現代框架(React、Vue、Angular)與純 DOM 操控
+- [ ] 貢獻開源 JavaScript 專案
+- [ ] 精通進階主題,如網頁元件和自定義元素
+- [ ] 打造高效能網頁應用,優化 DOM 操作
+- [ ] 教授他人 DOM 操控與 JavaScript 基礎
+
+## 🎯 你的 JavaScript DOM 掌握進度
+
+```mermaid
+timeline
+ title DOM 與 JavaScript 學習進度
+
+ section 基礎 (15 分鐘)
+ DOM 理解: 元素選取方法
+ : 樹狀結構導航
+ : 屬性存取模式
+
+ section 事件處理 (20 分鐘)
+ 使用者互動: 指標事件基礎
+ : 事件監聽器設定
+ : 跨裝置相容性
+ : 事件阻止技術
+
+ section 閉包 (25 分鐘)
+ 範圍管理: 私有變數建立
+ : 函式持續存在
+ : 狀態管理模式
+ : 記憶體效率
+
+ section 拖曳系統 (30 分鐘)
+ 互動功能: 座標追蹤
+ : 位置計算
+ : 移動數學
+ : 清理程序
+
+ section 進階模式 (45 分鐘)
+ 專業技能: 事件代理
+ : 性能優化
+ : 錯誤處理
+ : 無障礙考量
+
+ section 框架理解 (1 週)
+ 現代開發: 虛擬 DOM 概念
+ : 狀態管理函式庫
+ : 元件架構
+ : 建置工具整合
+
+ section 專家級 (1 個月)
+ 進階 DOM API: 交集觀察器
+ : 變異觀察器
+ : 自訂元素
+ : 網頁元件
+```
+### 🛠️ 你的 JavaScript 工具包總結
-雖然在屏幕上拖拽元素看起來很簡單,但有許多實現方式和潛在的陷阱,具體取決於你想要的效果。事實上,有一個完整的 [拖拽 API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) 可以嘗試。我們在本模組中沒有使用該 API,因為我們想要的效果有些不同,但你可以在自己的項目中嘗試這個 API,看看能實現什麼。
+完成本課後,你已具備:
+- **DOM 精通**:元素選取、屬性操作、樹狀結構導覽
+- **事件專業**:跨裝置指標事件互動處理
+- **閉包理解**:私有狀態管理與函式持續性
+- **互動系統**:從零打造完整拖放實作
+- **效能意識**:妥善清理事件避免記憶體洩漏
+- **現代模式**:專業開發中的程式碼組織技巧
+- **用戶體驗**:打造直覺、響應式界面
-在 [W3C 文檔](https://www.w3.org/TR/pointerevents1/) 和 [MDN 網頁文檔](https://developer.mozilla.org/docs/Web/API/Pointer_events) 上找到更多關於指針事件的信息。
+**你已習得的專業技能:**
+- **Trello/看板列表**:欄位間的卡片拖曳
+- **檔案上傳系統**:拖放檔案處理
+- **圖片庫**:照片重新排列介面
+- **行動應用**:基於觸控的互動模式
-隨時使用 [CanIUse.com](https://caniuse.com/) 檢查瀏覽器的兼容性。
+**下一階段**:你已準備好探索 React、Vue 或 Angular 等現代框架,這些框架基於你目前 DOM 操控的基本概念建立!
## 作業
-[進一步練習 DOM](assignment.md)
+[多練習操作 DOM](assignment.md)
---
+
**免責聲明**:
-本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,請注意自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。
\ No newline at end of file
+本文件乃使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們力求準確,但請注意自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應視為權威資料來源。對於重要資訊,建議採用專業人工翻譯。我們不對因使用本翻譯而產生的任何誤解或誤釋負責。
+
\ No newline at end of file
diff --git a/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/assignment.md b/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/assignment.md
index f5b4921aa..4b81d7fc4 100644
--- a/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/assignment.md
+++ b/translations/hk/3-terrarium/3-intro-to-DOM-and-closures/assignment.md
@@ -1,23 +1,139 @@
-# 多了解一些 DOM
+# DOM 元素調查作業
-## 指引
+## 概覽
-深入研究 DOM,嘗試「採用」一個 DOM 元素。造訪 MDN 的 [DOM 接口列表](https://developer.mozilla.org/docs/Web/API/Document_Object_Model),選擇其中一個。然後在網頁中找到它的使用範例,並撰寫一段解釋說明它是如何被使用的。
+現在你已經親身體驗了 DOM 操作的威力,是時候探索更廣泛的 DOM 介面世界。此作業將加深你對不同網頁技術如何與 DOM 互動的理解,而不僅僅是拖曳元素。
+
+## 學習目標
+
+完成此作業後,你將能夠:
+- **研究** 並深入了解特定的 DOM 介面
+- **分析** 實際應用中的 DOM 操作實現
+- **連結** 理論概念與實務應用
+- **培養** 技術文件撰寫與分析能力
+
+## 指示
+
+### 第一步:選擇你的 DOM 介面
+
+造訪 MDN 的完整 [DOM 介面列表](https://developer.mozilla.org/docs/Web/API/Document_Object_Model),並選擇一個你感興趣的介面。建議從以下類別中挑選,以豐富學習內容:
+
+**初學者友善選項:**
+- `Element.classList` - 動態管理 CSS 類別
+- `Document.querySelector()` - 進階元素選取
+- `Element.addEventListener()` - 指標事件以外的事件處理
+- `Window.localStorage` - 用戶端資料儲存
+
+**中級挑戰:**
+- `Intersection Observer API` - 偵測元素可見性
+- `MutationObserver` - 監視 DOM 變化
+- `Drag and Drop API` - 指標拖曳替代方案
+- `Geolocation API` - 取得用戶位置
+
+**進階探索:**
+- `Web Components` - 自訂元素與 Shadow DOM
+- `Canvas API` - 程式化繪圖
+- `Web Workers` - 背景處理
+- `Service Workers` - 離線功能
+
+### 第二步:研究並撰寫文件
+
+撰寫一份 300-500 字的完整分析內容,包含:
+
+#### 技術概述
+- **定義** 你所選介面是什麼,並以清楚且初學者友善的語言說明
+- **說明** 其主要方法、屬性或事件
+- **描述** 該介面設計用來解決的問題類型
+
+#### 實際應用
+- **尋找** 一個使用該介面的網站(檢查原始碼或搜尋範例)
+- **記錄** 具體的實現方式,若可能附上程式碼片段
+- **分析** 為什麼開發者會採用這種方案
+- **解釋** 它如何提升使用者體驗
+
+#### 實務應用
+- **比較** 你選的介面與我們在 terrarium 專案中使用的方法
+- **建議** 這個介面如何增強或擴展 terrarium 功能
+- **指出** 其他適合使用此介面的項目
+
+### 第三步:程式碼範例
+
+包含一個簡單且可執行的程式碼範例,展現你的介面實際運作。此程式碼應該:
+- **具功能性** — 測試後可正確執行
+- **有註解** — 解釋各部分功能
+- **相關性** — 與實際使用案例相關
+- **適合初學者** — 容易被學習網頁開發的人理解
+
+## 繳交格式
+
+請使用清楚的標題結構來安排你的提交內容:
+
+```markdown
+# [Interface Name] DOM Investigation
+
+## What It Does
+[Technical overview]
+
+## Real-World Example
+[Website analysis and implementation details]
+
+## Code Demonstration
+[Your working example with comments]
+
+## Reflection
+[How this connects to our terrarium project and future applications]
+```
## 評分標準
-| 評分項目 | 優秀 | 合格 | 需要改進 |
-| -------- | ------------------------------------------- | ---------------------------------------------- | ---------------------- |
-| | 提供段落式的說明,並附上範例 | 提供段落式的說明,但未附上範例 | 未提供任何說明 |
+| 評分準則 | 優異 (A) | 精熟 (B) | 發展中 (C) | 需改進 (D) |
+|----------|-----------|----------|------------|------------|
+| **技術理解** | 展現深刻理解,說明精準且用詞恰當 | 展示紮實理解,多數說明準確 | 基本理解,有部分誤解 | 理解不足,錯誤明顯 |
+| **實際分析** | 定位且徹底分析真實案例並具體說明 | 找到實例且分析一定程度充分 | 找到案例但分析較淺 | 實體連結不清或錯誤 |
+| **程式碼範例** | 工作正常且註解清晰,明確演示介面 | 功能正常且有適當註解 | 程式有效,但說明不足 | 程式有錯誤或解釋差 |
+| **文筆品質** | 文字清晰且吸引人,結構完善且具技術溝通能力 | 結構良好且技術寫作佳 | 結構與清晰度尚可 | 結構鬆散或表達不清 |
+| **批判性思考** | 深刻連結概念,提出創新應用建議 | 有分析思考並相關連結 | 有部分分析但不夠深入 | 缺乏批判性思考跡象 |
+
+## 成功秘訣
+
+**研究策略:**
+- **從** MDN 文件開始,取得權威資訊
+- **尋找** GitHub 或 CodePen 的程式碼範例
+- **利用** 瀏覽器開發工具檢查熱門網站
+- **觀看** 教學影片以獲得視覺說明
+
+**寫作指導:**
+- **用** 自己的話說明,不要照抄文件
+- **包含** 具體範例及程式碼片段
+- **用** 教學的語氣解釋技術概念
+- **將** 介面與更廣泛的網頁開發概念連結
+
+**程式碼範例點子:**
+- **製作** 展示介面主要功能的簡單示範
+- **延伸** 我們 terrarium 專案相關的概念
+- **重點** 放在功能性而非視覺設計
+- **測試** 程式碼,確保可正常執行
+
+## 繳交截止日
+
+[在此插入截止日期]
+
+## 有問題嗎?
+
+如需釐清任何相關問題,歡迎隨時詢問!本次調查將深化你對 DOM 如何支援日常網頁互動體驗的理解。
+
+---
+
**免責聲明**:
-本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。雖然我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始語言的文件應被視為具權威性的來源。對於重要資訊,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。
\ No newline at end of file
+本文件由 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 協助翻譯。雖然我們致力於確保準確性,但請注意自動翻譯可能包含錯誤或不準確之處。原始語言版本的文件應被視為權威來源。對於關鍵資訊,建議採用專業人工翻譯。我們不對因使用本翻譯而產生的任何誤解或誤釋負責。
+
\ No newline at end of file
diff --git a/translations/hk/3-terrarium/README.md b/translations/hk/3-terrarium/README.md
index 47879336f..d85087c9e 100644
--- a/translations/hk/3-terrarium/README.md
+++ b/translations/hk/3-terrarium/README.md
@@ -1,43 +1,30 @@
-# 我的微型植物園:一個學習 HTML、CSS 和使用 JavaScript 操控 DOM 的項目 🌵🌱
+## 部署你的 Terrarium
-一個小型的拖放式程式冥想。只需少量的 HTML、JS 和 CSS,你就能建立一個網頁介面,為其設計樣式,甚至添加多種互動功能。
+你可以使用 **Azure Static Web Apps** 在網絡上部署或發佈你的 Terrarium。
-
+1. 分叉此倉庫
-# 課程
+2. 按下此按鈕 👇
-1. [HTML 入門](./1-intro-to-html/README.md)
-2. [CSS 入門](./2-intro-to-css/README.md)
-3. [DOM 和 JS 閉包入門](./3-intro-to-DOM-and-closures/README.md)
+[](https://portal.azure.com/#create/Microsoft.StaticApp)
-## 致謝
+3. 按照設置嚮導創建你的應用。
+ - 將 **App root** 設定為 `/solution` 或你的代碼庫根目錄。
+ - 這個應用沒有 API,因此你可以跳過 API 配置。
+ - 系統會自動創建一個 `.github` 文件夾,以幫助 Azure Static Web Apps 構建和發佈你的應用。
-由 [Jen Looper](https://www.twitter.com/jenlooper) 用 ♥️ 編寫。
-
-透過 CSS 創建的微型植物園靈感來自 Jakub Mandra 的玻璃罐 [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY)。
-
-藝術作品由 [Jen Looper](http://jenlooper.com) 手繪,並使用 Procreate 協助完成。
-
-## 部署你的微型植物園
-
-你可以使用 Azure 靜態網頁應用程式將你的微型植物園部署或發布到網絡上。
-
-1. Fork 此倉庫
-
-2. 按下這個按鈕
-
-[](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
-
-3. 按照向導步驟創建你的應用程式。請確保將應用程式根目錄設置為 `/solution` 或你的代碼庫根目錄。此應用程式中沒有 API,因此不需要添加相關內容。一個 GitHub 文件夾將會在你 Fork 的倉庫中創建,幫助 Azure 靜態網頁應用程式的構建服務,構建並發布你的應用程式到一個新的 URL。
+---
+
**免責聲明**:
-本文件使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原文文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋概不負責。
\ No newline at end of file
+本文件乃使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於確保準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應視為權威來源。對於重要資訊,建議尋求專業人工翻譯。我們不對因使用本翻譯而產生的任何誤解或誤釋負責。
+
\ No newline at end of file
diff --git a/translations/hk/4-typing-game/README.md b/translations/hk/4-typing-game/README.md
index 69b6e38e1..ad0252fec 100644
--- a/translations/hk/4-typing-game/README.md
+++ b/translations/hk/4-typing-game/README.md
@@ -1,42 +1,290 @@
-# 事件驅動編程 - 建立一個打字遊戲
+# 事件驅動程式設計 - 建立一個打字遊戲
-## 簡介
+```mermaid
+journey
+ title 你的打字遊戲開發旅程
+ section 基礎
+ 計劃遊戲結構: 3: Student
+ 設計用戶界面: 4: Student
+ 設置 HTML 元素: 4: Student
+ section 功能
+ 處理用戶輸入: 4: Student
+ 跟蹤時間: 5: Student
+ 計算準確度: 5: Student
+ section 功能特色
+ 增加視覺反饋: 5: Student
+ 實現遊戲邏輯: 5: Student
+ 美化體驗: 5: Student
+```
+## 介紹
-打字是開發者最被低估的技能之一。能夠快速將腦海中的想法轉移到編輯器中,能讓創意自由流動。學習的最佳方式之一就是玩遊戲!
+有一件每個開發者都知道但很少談論的事:打字快是超能力!🚀 想想看——你越快把腦中的想法輸入到程式編輯器,創造力就能流動得越順暢。就像你的思緒和螢幕之間有條直接的管道。
-> 那麼,讓我們來建立一個打字遊戲吧!
+```mermaid
+pie title 遊戲功能
+ "即時反饋" : 25
+ "效能追蹤" : 20
+ "互動介面" : 20
+ "計時系統" : 15
+ "引言管理" : 10
+ "結果顯示" : 10
+```
+想知道提升這項技能的最佳方法之一嗎?你猜對了——我們要做一款遊戲!
-你將使用迄今為止學到的 JavaScript、HTML 和 CSS 技能來創建一個打字遊戲。遊戲會向玩家展示一段隨機的名言(我們使用的是 [福爾摩斯](https://en.wikipedia.org/wiki/Sherlock_Holmes) 的名言),並計算玩家準確輸入這段文字所需的時間。你將使用迄今為止學到的 JavaScript、HTML 和 CSS 技能來創建一個打字遊戲。
+```mermaid
+flowchart LR
+ A[玩家開始遊戲] --> B[隨機顯示語錄]
+ B --> C[玩家輸入字元]
+ C --> D{字元正確嗎?}
+ D -->|是| E[綠色高亮]
+ D -->|否| F[紅色高亮]
+ E --> G[更新準確率]
+ F --> G
+ G --> H{語錄完成了嗎?}
+ H -->|否| C
+ H -->|是| I[計算每分鐘字數]
+ I --> J[顯示結果]
+ J --> K[再玩一次?]
+ K -->|是| B
+ K -->|否| L[遊戲結束]
+
+ style A fill:#e1f5fe
+ style D fill:#fff3e0
+ style E fill:#e8f5e8
+ style F fill:#ffebee
+ style I fill:#f3e5f5
+```
+> 讓我們一起創造一款超棒的打字遊戲吧!
+準備好運用你學習的 JavaScript、HTML 和 CSS 技能了嗎?我們要建立一個打字遊戲,遊戲內容會挑戰你打出來自傳奇偵探 [Sherlock Holmes](https://en.wikipedia.org/wiki/Sherlock_Holmes) 的隨機名言。遊戲會追蹤你打字的速度和準確性——相信我,這比你想像中還要令人上癮!
+
+```mermaid
+mindmap
+ root((打字遊戲開發))
+ User Interface
+ Input Elements
+ Visual Feedback
+ Responsive Design
+ Accessibility
+ Game Logic
+ Quote Selection
+ Timer Management
+ Accuracy Tracking
+ Score Calculation
+ Event Handling
+ Keyboard Input
+ Button Clicks
+ Real-time Updates
+ Game State Changes
+ Performance Metrics
+ Words Per Minute
+ Character Accuracy
+ Error Tracking
+ Progress Display
+ User Experience
+ Immediate Feedback
+ Clear Instructions
+ Engaging Content
+ Achievement System
+```

-## 先決條件
+## 你需要知道的
-本課假設你已熟悉以下概念:
+```mermaid
+flowchart TD
+ A[用戶動作] --> B{事件類型?}
+ B -->|鍵盤按鍵| C[鍵盤事件]
+ B -->|按鈕點擊| D[滑鼠事件]
+ B -->|計時器| E[時間事件]
+
+ C --> F[檢查字元]
+ D --> G[開始/重設遊戲]
+ E --> H[更新計時器]
+
+ F --> I{正確?}
+ I -->|是| J[標示綠色]
+ I -->|否| K[標示紅色]
+
+ J --> L[更新分數]
+ K --> L
+ L --> M[檢查遊戲狀態]
+
+ G --> N[生成新名言]
+ H --> O[顯示時間]
+
+ M --> P{遊戲完成?}
+ P -->|是| Q[顯示結果]
+ P -->|否| R[繼續遊戲]
+
+ style A fill:#e1f5fe
+ style F fill:#e8f5e8
+ style I fill:#fff3e0
+ style Q fill:#f3e5f5
+```
+在深入之前,請確保你熟悉以下概念(如果需要快速複習也沒關係——我們都經歷過!):
-- 創建文字輸入框和按鈕控件
-- CSS 和使用類別設置樣式
+- 建立文字輸入和按鈕控件
+- CSS 與使用類別設定樣式
- JavaScript 基礎
- - 創建數組
- - 生成隨機數
- - 獲取當前時間
+ - 建立陣列
+ - 產生隨機數字
+ - 取得目前時間
+
+如果有任何部分感覺有點生疏,也完全沒問題!有時候鞏固知識的最好方式就是開始實作,邊做邊學。
+
+### 🔄 **教學確認**
+**基礎評估**:開始開發前,確保你了解:
+- ✅ HTML 表單與輸入元素的工作原理
+- ✅ CSS 類別與動態樣式設定
+- ✅ JavaScript 事件監聽器與處理程序
+- ✅ 陣列操作與隨機選擇
+- ✅ 時間測量與計算
+
+**快速自我測驗**:你能解釋這些概念如何在互動遊戲中協同運作嗎?
+- **事件** 在使用者與元素互動時觸發
+- **處理程序** 負責處理事件並更新遊戲狀態
+- **CSS** 提供使用者行為的視覺反饋
+- **計時** 使得效能測量和遊戲進展成為可能
+
+```mermaid
+quadrantChart
+ title 打字遊戲技能發展
+ x-axis 初學者 --> 專家
+ y-axis 靜態 --> 互動式
+ quadrant-1 進階遊戲
+ quadrant-2 即時應用程式
+ quadrant-3 基本頁面
+ quadrant-4 互動網站
+
+ HTML Forms: [0.3, 0.2]
+ CSS Styling: [0.4, 0.3]
+ Event Handling: [0.7, 0.8]
+ Game Logic: [0.8, 0.9]
+ Performance Tracking: [0.9, 0.7]
+```
+## 開工吧!
+
+[利用事件驅動程式設計創建打字遊戲](./typing-game/README.md)
+
+### ⚡ **接下來 5 分鐘你可以做什麼**
+- [ ] 開啟瀏覽器主控台,試試用 `addEventListener` 監聽鍵盤事件
+- [ ] 建立一個簡單 HTML 頁面,有輸入欄並測試打字偵測
+- [ ] 練習字串操作,將輸入文字與目標文字比對
+- [ ] 嘗試使用 `setTimeout` 理解定時功能
-## 課程
+### 🎯 **這一小時你可以完成什麼**
+- [ ] 完成課後小測,理解事件驅動程式設計
+- [ ] 建立打字遊戲的基本版本並驗證字詞
+- [ ] 新增正確與錯誤打字的視覺反饋
+- [ ] 實作基於速度與準確性的簡單計分系統
+- [ ] 用 CSS 美化遊戲介面,使之更吸引人
-[使用事件驅動編程創建打字遊戲](./typing-game/README.md)
+### 📅 **這一週你的遊戲開發路線**
+- [ ] 完成具備所有功能與細節的完整打字遊戲
+- [ ] 新增難度等級,包含不同複雜度的字詞
+- [ ] 實作用戶統計追蹤(WPM、準確率變化)
+- [ ] 添加音效與動畫,提升使用體驗
+- [ ] 讓遊戲響應式適用於觸控裝置
+- [ ] 將遊戲分享線上並收集用戶回饋
+
+### 🌟 **這一個月你的互動開發計畫**
+- [ ] 開發多款遊戲,探索不同互動模式
+- [ ] 學習遊戲循環、狀態管理與效能優化
+- [ ] 貢獻開源遊戲開發專案
+- [ ] 精通高階計時概念與流暢動畫
+- [ ] 建立展示各式互動應用的作品集
+- [ ] 指導其他對遊戲開發與用戶互動有興趣的人
+
+## 🎯 你的打字遊戲精通時間表
+
+```mermaid
+timeline
+ title 遊戲開發學習進度
+
+ section 設置 (10分鐘)
+ 專案結構: HTML 基礎
+ : CSS 樣式設置
+ : JavaScript 檔案建立
+
+ section 使用者介面 (20分鐘)
+ 互動元素: 輸入欄位
+ : 按鈕控制
+ : 顯示區域
+ : 響應式佈局
+
+ section 事件處理 (25分鐘)
+ 使用者互動: 鍵盤事件
+ : 滑鼠事件
+ : 即時反饋
+ : 狀態管理
+
+ section 遊戲邏輯 (30分鐘)
+ 核心功能: 引言產生
+ : 角色比較
+ : 精確度計算
+ : 計時器實作
+
+ section 性能追蹤 (35分鐘)
+ 指標與分析: 每分鐘字數計算
+ : 錯誤追蹤
+ : 進度可視化
+ : 結果顯示
+
+ section 美化與增強 (45分鐘)
+ 使用者體驗: 視覺反饋
+ : 音效
+ : 動畫
+ : 無障礙功能
+
+ section 進階功能 (1週)
+ 擴展功能: 難度等級
+ : 排行榜
+ : 自訂引言
+ : 多人選項
+
+ section 專業技能 (1個月)
+ 遊戲開發: 性能優化
+ : 代碼架構
+ : 測試策略
+ : 部署模式
+```
+### 🛠️ 你的遊戲開發工具包總結
+
+完成這個專案後,你將掌握:
+- **事件驅動程式設計**:對輸入反應的互動界面
+- **即時反饋**:快速視覺與效能更新
+- **效能測量**:精確的計時與計分系統
+- **遊戲狀態管理**:控制應用流程與用戶體驗
+- **互動設計**:創造引人入勝、令人上癮的使用體驗
+- **現代網頁 API**:利用瀏覽器能力實現豐富互動
+- **無障礙模式**:為所有使用者打造包容性設計
+
+**實際應用場景**:這些技能適用於:
+- **網頁應用程式**:任何互動界面或儀表板
+- **教育軟體**:學習平台與技能評估工具
+- **生產力工具**:文字編輯器、整合開發環境、協作軟體
+- **遊戲產業**:瀏覽器遊戲與互動娛樂
+- **行動開發**:觸控介面與手勢處理
+
+**下一階段**:準備探索進階遊戲框架、即時多人系統或複雜的互動應用!
## 致謝
-由 [Christopher Harrison](http://www.twitter.com/geektrainer) 用 ♥️ 編寫
+由 [Christopher Harrison](http://www.twitter.com/geektrainer) 以 ♥️ 撰寫
+
+---
+
**免責聲明**:
-本文件使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原文文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。
\ No newline at end of file
+本文件乃使用人工智能翻譯服務【Co-op Translator】(https://github.com/Azure/co-op-translator) 翻譯而成。雖然我們致力於確保準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威資料。對於重要資訊,建議使用專業人工翻譯。對於因使用本翻譯而引致的任何誤解或誤釋,我們概不負責。
+
\ No newline at end of file
diff --git a/translations/hk/4-typing-game/typing-game/README.md b/translations/hk/4-typing-game/typing-game/README.md
index 55bc34ad0..a6797a17f 100644
--- a/translations/hk/4-typing-game/typing-game/README.md
+++ b/translations/hk/4-typing-game/typing-game/README.md
@@ -1,88 +1,154 @@
-# 使用事件創建遊戲
+# 使用事件創建一個遊戲
+
+你是否曾經想過網站如何知道你何時點按按鈕或在文字框中輸入?這就是事件驅動程式設計的魔力!有什麼比構建一個有用的東西更好的方式來學習這項基本技能呢——一個會對你每次敲打的按鍵作出反應的打字速度遊戲。
+
+你將親身看到網頁瀏覽器如何「與」你的 JavaScript 代碼「對話」。每次你點按、輸入或移動滑鼠時,瀏覽器都會向你的代碼發送小訊息(我們稱之為事件),而你則決定如何回應!
+
+到本文結束時,你將建立一個真實的打字遊戲,追蹤你的速度和準確度。更重要的是,你將理解驅動每一個你曾使用過的互動網站的基本概念。讓我們開始吧!
## 課前測驗
-[課前測驗](https://ff-quizzes.netlify.app/web/quiz/21)
+[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/21)
+
+## 事件驅動程式設計
-## 事件驅動編程
+想想你最喜歡的應用程式或網站——是什麼令它感覺生動且反應靈敏?全在於它如何回應你的操作!每一次點按、點擊、滑動或鍵入都會創造一個我們稱之為「事件」的東西,而這正是網頁開發中真正的魔法所在。
-當我們創建一個基於瀏覽器的應用程式時,我們會提供一個圖形用戶介面(GUI),讓用戶在與我們構建的內容互動時使用。與瀏覽器互動最常見的方式是通過點擊和在各種元素中輸入文字。作為開發者,我們面臨的挑戰是,我們不知道用戶什麼時候會執行這些操作!
+這就是為什麼針對網頁編程如此有趣的原因:我們永遠不知道何時有人會點擊按鈕或開始輸入文字。他們可能立即點擊,也可能等待五分鐘,或者可能根本不點擊!這種不可預測性意味著我們需要用不同的方法來撰寫代碼。
-[事件驅動編程](https://en.wikipedia.org/wiki/Event-driven_programming) 是我們需要用來創建 GUI 的編程類型。如果我們稍微拆解這個詞語,我們會發現核心詞是 **事件**。根據 Merriam-Webster 的定義,[事件](https://www.merriam-webster.com/dictionary/event) 是指「某件發生的事情」。這完美地描述了我們的情況。我們知道會有某些事情發生,我們希望在這些事情發生時執行一些代碼,但我們不知道它們什麼時候會發生。
+我們不是寫一段從上到下運行的程式碼(就像食譜一樣),而是寫程式碼耐心地等待事情發生。這就像 1800 年代的電報操作員守候在他們的機器旁,準備在訊息通過電線時立即回應一樣。
-我們通過創建函數來標記我們希望執行的代碼部分。在 [程序式編程](https://en.wikipedia.org/wiki/Procedural_programming) 中,函數是按照特定順序調用的。在事件驅動編程中也是如此,不同之處在於函數是 **如何** 被調用的。
+那麼,「事件」究竟是什麼?簡單地說,它是發生的事情!你點擊一個按鈕——這就是一個事件。你輸入一個字母——這是另一個事件。你移動滑鼠——還有另一個事件。
-為了處理事件(如按鈕點擊、輸入等),我們需要註冊 **事件監聽器**。事件監聽器是一個函數,它會監聽某個事件的發生並在事件發生時執行。事件監聽器可以更新用戶介面、向伺服器發送請求,或者執行其他需要根據用戶操作完成的任務。我們可以使用 [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) 並提供一個函數來添加事件監聽器。
+事件驅動程式設計讓我們能夠設定代碼來聆聽和回應。我們創建特殊函數稱為**事件監聽器(event listeners)**,它們耐心等待特定事件發生,然後在事件發生時立即執行。
-> **NOTE:** 值得一提的是,創建事件監聽器有很多種方式。你可以使用匿名函數,也可以創建命名函數。你還可以使用一些快捷方式,比如設置 `click` 屬性,或者使用 `addEventListener`。在我們的練習中,我們將專注於使用 `addEventListener` 和匿名函數,因為這是網頁開發者最常用的技術之一。它也是最靈活的,因為 `addEventListener` 適用於所有事件,並且事件名稱可以作為參數提供。
+把事件監聽器想像成你的代碼的門鈴。你安裝門鈴 (`addEventListener()`),告訴它要聽哪種聲音(如「click」或「keypress」),然後指定誰按鐘時該做什麼(你的自訂函數)。
+
+**事件監聽器的工作原理:**
+- **監聽**特定的用戶操作,如點擊、鍵擊或滑鼠移動
+- **執行**指定事件發生時的自訂代碼
+- **立即回應**用戶互動,創造無縫體驗
+- **可處理**同一元素上的多個不同事件監聽器
+
+> **NOTE:** 值得一提的是,創建事件監聽器的方法有很多。你可以使用匿名函數,或者建立有名稱的函數。你也可以用各種快捷方式,比如設定 `click` 屬性,或者使用 `addEventListener()`。在我們的練習中,我們將專注於 `addEventListener()` 和匿名函數,因為這可能是網頁開發者最常用的技術。它也是最靈活的,因為 `addEventListener()` 適用於所有事件,且事件名稱可作為參數傳入。
### 常見事件
-在創建應用程式時,有[數十種事件](https://developer.mozilla.org/docs/Web/Events)可供監聽。基本上,用戶在頁面上執行的任何操作都會觸發事件,這讓你擁有很大的控制力來確保用戶獲得你期望的體驗。幸運的是,你通常只需要使用少數幾種事件。以下是一些常見的事件(包括我們在創建遊戲時會用到的兩個):
+雖然網頁瀏覽器提供數十種不同的事件可供監聽,但大多數互動應用程式只依賴幾個基本事件。理解這些核心事件將為你建立複雜的用戶互動奠定基礎。
+
+有[數十種事件](https://developer.mozilla.org/docs/Web/Events)可供你監聽,幾乎用戶在頁面上做的任何事情都可以引發事件,這讓你能夠掌控用戶體驗。幸運的是,你通常只需要少數幾種事件。以下是一些常見的(包括我們創建遊戲時將使用的兩種):
-- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event):用戶點擊某個元素,通常是按鈕或超連結
-- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event):用戶點擊滑鼠右鍵
-- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event):用戶選取了一些文字
-- [input](https://developer.mozilla.org/docs/Web/API/Element/input_event):用戶輸入了一些文字
+| Event | 說明 | 常見用例 |
+|-------|-------|---------|
+| `click` | 用戶點擊了某些東西 | 按鈕、鏈結、互動元素 |
+| `contextmenu` | 用戶點擊了滑鼠右鍵 | 自訂右鍵選單 |
+| `select` | 用戶選取了部分文字 | 文字編輯、複製操作 |
+| `input` | 用戶輸入了文字 | 表單驗證、即時搜尋 |
+
+**理解這些事件類型:**
+- **觸發**用戶與頁面上特定元素互動
+- **提供**關於用戶操作的詳細事件對象資訊
+- **啟用**你創造反應迅速、互動性強的網頁應用程式
+- **跨瀏覽器裝置**皆可一致運作
## 創建遊戲
-我們將創建一個遊戲來探索 JavaScript 中的事件是如何工作的。我們的遊戲將測試玩家的打字技能,這是所有開發者應該具備但經常被低估的一項技能。我們都應該練習打字!遊戲的基本流程如下:
+既然你了解事件如何運作,讓我們將這些知識付諸實踐,做一些有用的東西。我們將建立一個打字速度遊戲,演示事件處理的同時幫助你培養重要的開發技能。
+
+我們要創建一個遊戲來探索 JavaScript 中事件的運作。遊戲將測試玩家的打字技能,這是每個開發者都應該擁有且被低估的技能。趣聞:我們如今使用的 QWERTY 鍵盤布局其實是在 1870 年代為打字機設計的——而良好的打字技能對程式設計師來說依然十分有價值!遊戲的一般流程如下:
+
+```mermaid
+flowchart TD
+ A[玩家點擊開始] --> B[顯示隨機名言]
+ B --> C[玩家在文字框輸入]
+ C --> D{單字完成?}
+ D -->|是| E[突出顯示下一個單字]
+ D -->|否| F{目前正確嗎?}
+ F -->|是| G[保持正常樣式]
+ F -->|否| H[顯示錯誤樣式]
+ E --> I{名言完成?}
+ I -->|否| C
+ I -->|是| J[顯示成功訊息和時間]
+ G --> C
+ H --> C
+```
+**遊戲流程:**
+- **開始**:玩家按下開始按鈕,顯示一段隨機引言
+- **追蹤**:即時追蹤玩家的逐字輸入進度
+- **標示**:高亮顯示當前字詞,引導玩家專注
+- **回饋**:立即以視覺效果提示輸入錯誤
+- **計算**:完成全部引言時顯示花費的總時間
-- 玩家點擊開始按鈕,並看到一段需要輸入的文字
-- 玩家在文本框中盡可能快地輸入這段文字
- - 每完成一個單詞,下一個單詞會被高亮顯示
- - 如果玩家輸入錯誤,文本框會變成紅色
- - 當玩家完成整段文字時,會顯示成功訊息以及所用時間
+讓我們一起開發遊戲,並了解事件!
-讓我們開始構建遊戲,並學習事件的相關知識吧!
+### 檔案結構
-### 文件結構
+在撰寫代碼前,讓我們做好組織!有一個整潔的檔案結構能避免日後的麻煩,讓你的專案看起來更專業。😊
-我們需要三個文件:**index.html**、**script.js** 和 **style.css**。讓我們先設置這些文件,讓後續的工作更輕鬆。
+我們將保持簡單,只使用三個檔案:`index.html` 放我們的頁面結構,`script.js` 包含遊戲的邏輯,還有 `style.css` 讓頁面美觀。這是網頁開發最經典的三劍客!
-- 打開控制台或終端,輸入以下命令來創建一個新文件夾:
+**打開命令列或終端機視窗,輸入以下指令,來為你的工作建立一個新資料夾:**
```bash
-# Linux or macOS
+# Linux 或 macOS
mkdir typing-game && cd typing-game
# Windows
md typing-game && cd typing-game
```
-- 打開 Visual Studio Code
+**這些指令做了什麼:**
+- **創建**一個名為 `typing-game` 的新目錄,用來存放你的專案檔案
+- **自動切換到**新建的目錄中
+- **為你的遊戲開發搭建了**一個乾淨的工作環境
+
+**打開 Visual Studio Code:**
```bash
code .
```
-- 在 Visual Studio Code 中,為該文件夾添加以下三個文件:
- - index.html
- - script.js
- - style.css
+**此指令作用:**
+- **在目前目錄啟動** Visual Studio Code
+- **打開**你的專案資料夾到編輯器中
+- **提供**所有你需要的開發工具
+
+**在 Visual Studio Code 中新增三個檔案,命名如下:**
+- `index.html` - 包含遊戲的結構和內容
+- `script.js` - 處理所有遊戲邏輯和事件監聽器
+- `style.css` - 定義視覺外觀和樣式
+
+## 創建使用者介面
+
+現在讓我們搭建實際進行遊戲操作的舞台!把它想成為飛船設計控制面板——我們要確保玩家需要的所有東西都在他們預期的位置。
-## 創建用戶介面
+先想想遊戲需要些什麼。如果你在玩打字遊戲,你希望畫面上看到什麼?這裡是我們需要的:
-根據需求,我們知道我們的 HTML 頁面需要一些元素。這有點像食譜,我們需要一些材料:
+| UI 元素 | 用途 | HTML 元素 |
+|---------|-------|-----------|
+| 引言顯示區 | 顯示要輸入的文字 | ``,具有 `id="quote"` |
+| 訊息區域 | 顯示狀態及成功訊息 | `
`,具有 `id="message"` |
+| 文字輸入框 | 玩家輸入引言 | ``,具有 `id="typed-value"` |
+| 開始按鈕 | 開始遊戲 | `