HYUX LEARNING探索課程
回到短指令跟做教材 ↗下載工程說明 ↓操作外觀範例 ↗下載單一 HTML ↓下載原始碼 ZIP ↓

編者與前端工程選讀

本篇保存實作原理與工程檢查,供編者及想深入的讀者選讀。初學者請先閱讀「短指令跟做教材」,不需要先理解本篇參數或照寫工程提示詞。

先開啟原始參考網站:HEART 政策島。本篇接續「從企劃、資料到 3D 互動小島」的入門影片,練習把資料變成一座可旋轉、可點選、可切換日夜的模型城市。

使用者提供的第三方「創島提示詞」是本篇的需求參考;原貼文作者與網址尚未提供。六角座標、路網、小人與日夜等描述,在本篇都是獨立範例的實作選擇,不能據此推定原始網站的內部架構。

先看這次可操作的結果

開啟上方「進階可操作範例」。範例有 12 個主題、48 筆虛構提案、12 種程序模型,以及 8 條示意關係。它以原生 ES Modules 載入 Three.js 0.160.0,幾何與地面貼圖由程式產生,沒有外部圖片、模型或字型檔。

重要界線: 搬運角色與任務事件都標為教學示意,此頁沒有接上 AgentArk 或其他真實後端。內容數字不是政策統計;official/thematic/pending 在此只用來示範線型,並不表示虛構資料有真實官方認證。

實作檔案與版本

入門範例使用 Three.js 0.186.1;本篇獨立範例鎖定 0.160.0,配合第三方提示詞的版本。不直接替換入門專案依賴。

上方提供單一 HTML、進階教材與含測試的分檔原始碼 ZIP。解壓 ZIP 後,依 README 執行,不需要安裝 npm 依賴。來源採分檔管理,建置後產生可下載的單一 HTML。修改時依以下責任分工閱讀:

在教學庫根目錄執行:

node --test courses/public-learning-island/advanced/tests/core.test.mjs
node scripts/build-island-advanced.mjs
npm run build
npm run preview

預覽網址是 http://127.0.0.1:4173/courses/public-learning-island/advanced/。單一 HTML 仍需要網路下載鎖版 Three.js;建議用 HTTP 預覽。CDN 載入失敗時,文字探索應繼續可用。

第 1 階段:六角島、相機、光與橋

前置成果: 一份 DATA,至少三座相鄰島,並保留每座島的穩定 ID 與 axial 座標 q、r。

pointy-top 六角形的座標換算如下。SPACING 是公式中的尺寸參數,不是兩島中心距離。

const R = 2.02;
const SPACING = 2.28;
function axialToWorld(q, r) {
  return {
    x: Math.sqrt(3) * SPACING * (q + r / 2),
    z: 1.5 * SPACING * r
  };
}
// 相鄰中心距離:sqrt(3) × 2.28 ≈ 3.9491
// 平行邊之間水道:sqrt(3) × (2.28 - 2.02) ≈ 0.4503

島面用六角 CircleGeometry;側壁的朝向必須與島面一致,不能只看正上方就認定沒有重疊。步道沿六角形周圍配置頂點與邊中點,共 12 個節點。相鄰島以 axial 距離 1 判斷,橋連到彼此朝向的邊中點,每座橋拆成 9 片甲板,用 sin 曲線形成小拱。

相機採透視相機與窄視角,搭配 OrbitControls;選取時同時插值 camera.position 與 controls.target。使用者開始拖曳就取消飛行,避免程式與滑鼠搶控制。鳥瞰時要一併調整 polar angle 下限,否則控制器會把相機拉回原限制。

可複製提示詞 1

請建立原生 ES Modules 的單一 HTML 教學範例,Three.js 固定 0.160.0。
先用 DATA 放三座相鄰的虛構六角島,R=2.02、SPACING=2.28、TOP=0.65。
依 axial 公式計算位置,建立島面、側壁、步道與相鄰島之間的 9 片拱橋。
加入相機、OrbitControls、光線和可點選的島名標籤。
載入畫面與文字清單先出現,再在 try/catch 內 await import Three.js 與 addons。
選取島時同步移動相機與 target;使用者拖曳立即取消相機飛行。
本階段不要加入人流與複雜模型。交付可直接預覽的 index.html。

輸出與驗收: index.html 能以 HTTP 開啟,三島不相交,水道約 0.45;橋沒有懸空。拖曳、縮放、重設與島名按鈕可用,窄螢幕仍看得到島嶼。刻意阻斷 CDN,應看到載入錯誤與可讀清單。

第 2 階段:程序建物零件庫

前置成果: 第 1 階段可正常執行的 HTML,以及每筆細項的 model 欄位。

黏土城市的辨識度來自小型場景的組合:牆、屋頂、窗、桌椅、輪子與植栽。先建立固定幾何,再把位置、旋轉、縮放與顏色記成零件資料。模型函式只負責排零件。

// 概念節錄;完整版本見 kit.mjs
const parts = [];
function addPart(kind, matrix, color, itemId) {
  parts.push({ kind, matrix, color, itemId });
}
const factories = { house, hall, school, clinic, bus, bike,
  court, garden, stage, book, clock, globe };
factories[item.model]();
// 最後依 geometry/material 相容性分批建立 InstancedMesh。

本範例的 12 種模型由 DATA 指定,包含小屋、塔樓、教室、診所、公車站、腳踏車、球場、花圃、舞台、書、時鐘與地球儀。相同 geometry 重複使用;實例顏色保存原始值,選取與時段高亮都從原色重新計算,避免越點越紅。

固定種子要用在幾何抖動、植栽位置與程序地面紋理。本版 SimplexNoise 接收的是有 random 方法的物件:

const random = seeded(20261023);
const noise = new SimplexNoise({ random });

可複製提示詞 2

延續已可執行的第一階段,保留資料 ID、相機與橋。
加入零件庫,將 kind、matrix、color、itemId 收集後依幾何與材質分批實例化。
做 12 種小型模型,由 DATA.items[].model 決定,不以主題名稱寫死模型。
加入原始顏色表與 instance→itemId 反查表。
所有程序亂數用同一固定種子;SimplexNoise 使用 { random: seeded(seed) }。
加入少量植栽與街道家具,鏡頭拉遠時隱藏細節。
輸出更新後的 index.html,並列出本階段實測 draw calls 與 triangles。

輸出與驗收: 重新載入兩次,幾何位置相同。把一筆 model 改成 book,只改該筆視覺表示。48 筆細項皆有對應模型;選取一棟不會讓同批所有建物一起變色。20–30 calls 只能是特定批次的設計目標,完整場景數字必須實測。

第 3 階段:點選、卡片與手機介面

前置成果: 零件批次,以及由資料 ID 驅動的清單。

InstancedMesh 的一次命中會提供 object 與 instanceId;同一個 item 可能由不同批次的多個零件組成。先反查內容 ID,再讓清單、卡片、相機與高亮走同一個選取流程。

const hit = raycaster.intersectObjects(pickMeshes)[0];
const itemId = instanceToItem[hit.object.name][hit.instanceId];
select('item', itemId);
// 更新批次後:
mesh.instanceColor.needsUpdate = true;
mesh.instanceMatrix.needsUpdate = true;

指標座標必須依 canvas 的 bounding rect 換算;pointerdown 與 pointerup 位移超過 6px 視為拖曳。裝飾零件不映射內容 ID,讓拾取繼續檢查下一個命中。搜尋後被隱藏的模型,也不能繼續被選取。

手機清單放在底部面板,本版提供高度調整滑桿;單一按鈕最小可操作區域要夠大。文字清單保留鍵盤入口。CSS2DRenderer 官方只保證 100% 瀏覽器及顯示縮放,因此要另外驗收 200% 縮放,並維持清單可用。

可複製提示詞 3

延續第二階段,加入共用 selectedId 狀態、搜尋、主題清單與詳情卡片。
Raycaster 命中後依 mesh+instanceId 找到 itemId;整棟所有零件一起高亮。
清單按鈕與 3D 點擊共用 select,搜尋結果和場景同步。
拖曳超過 6px 不當成點擊。保留 Tab/Enter 選取與 Esc 關閉。
手機將清單改成可調整高度的底部面板,避免遮住所有 3D 內容。
交付 index.html,列出滑鼠、鍵盤、375px 的實際檢查步驟。

輸出與驗收: 搜尋典藏,選取「開放典藏工坊」;清單、卡片與 3D 指向同一筆。實際用滑鼠點模型,再用鍵盤選同一筆,結果應一致。拖曳不開卡片,手機沒有水平捲動。

第 4 階段:日夜、水面、路網與角色

前置成果: 可用的選取介面、幾何零件庫及六角步道。

日夜是一組可插值的場景參數。天空、horizon、霧、水色與光源一起更新;霧色跟 horizon 一致,避免遠景出現突兀色帶。夜晚用較強的冷色環境光保留可讀性,窗戶 emissive 隨 night 變化。水面 Shader 用兩組正弦波做色彩漂移,並支援霧與輸出色彩轉換。

角色行走必須沿可通行路網。每島 12 個節點連成環,橋加入跨島邊,Dijkstra 求最短路。依累積路程計算位置,不把角色沿兩島中心直線移動。本範例的小人以頭、髮、身體和兩腿五個動態批次繪製;到站交接紀錄與角色路程一致。

關係與路徑分開: 協作資料說明兩個主題的關係,路網只回答如何移動。pending 線可作為靜態待確認示意,不派出搬運角色。畫面所有搬運仍是教學動畫,不能拿來當真實流量或任務成效。

可複製提示詞 4

保留第三階段功能,加入可手動切換的清晨、白天、黃昏、夜晚。
以 keyframes 插值天空、水色、霧與光線,night 控制窗戶 emissive。
步道建立每島 12 節點環;相鄰島的橋接到邊中點,Dijkstra 尋路。
角色依弧長沿路線往返,到站停留後交接,日誌標示「示意搬運」。
pending 關係用靜態虛線說明,不產生搬運角色。
暫停與 prefers-reduced-motion 必須讓時間、角色、水面、雲與自動日誌停止;
手動操作仍可使用。交付 index.html 與暫停前後的觀察結果。

輸出與驗收: 夜晚文字和建物仍可辨識。角色過橋,不穿海;到站交接與日誌相符。暫停數秒後,時間、角色及日誌不增加;在系統減少動態偏好變更後,立即停止動態,選取相機直接定位。

第 5 階段:接真實事件,並測完整場景

前置成果: 前四階段穩定可操作,且已定義真實系統能提供什麼事件。

若要顯示 Agent 或工作系統的實際運作,另接事件契約。不要依角色走到目的地就推定任務完成。本範例提供 receiveIslandEvent(event) 入口與本機示意按鈕,未設定任何外部連線。

{
  "eventId": "evt-1024",
  "agentId": "worker-a",
  "taskId": "job-42",
  "itemId": "item-26",
  "seq": 2,
  "status": "completed",
  "occurredAt": "2026-10-23T08:00:00Z",
  "source": "external"
}

資料入口先檢查已知 item、合法狀態、有效時間與遞增序號;相同 eventId、過期序號與非法內容不更新畫面。本版序號以每個 item 為範圍,正式後端應由伺服器提供該 item 的單調版本,避免不同任務各自從 1 開始互相覆寫。agentId、taskId 保留為追溯資訊。

// 後端適配器收到已驗證事件後才呼叫;此段不代表已連線。
receiveIslandEvent(event);
// 可選用 SSE/WebSocket/輪詢;先定義斷線、重連與快照恢復。
// 不把 token 寫進公開 HTML,瀏覽器僅接收有權限閱讀的資料。

本版 seen 僅保留最近 1,000 個 eventId,日誌保留 40 筆,屬於有界的前端顯示邏輯。正式系統的長期去重、儲存、權限與事件真實性由後端負責。選到過濾結果以外的項目時,需先定義是否顯示提示或清除選取。

可複製提示詞 5

保留既有場景與原始資料,加入獨立 receiveIslandEvent 入口。
事件有 eventId、agentId、taskId、itemId、seq、status、occurredAt、source。
同一 item 用伺服器單調 seq;重複、過期、未知 item 與非法狀態不更新。
先用明示「本機示意」的按鈕驗證狀態、高亮、卡片與日誌同步;
沒有後端資料時,不顯示已連線或真實 LIVE。
量測完整場景 calls、triangles、首次可操作與互動幀時間;
檢查 375px、200% 縮放、鍵盤、真實觸控、減少動態與載入失敗。
輸出 index.html、事件契約,以及已測/未測的驗收紀錄。

輸出與驗收: 同一事件送兩次,日誌不增加;較小 seq 不能把 completed 改回 running;合法新事件能更新卡片與建物。WebGL 或 CDN 不可用時,搜尋、文字與示意任務仍能操作。實測呼叫數不與幾何批次數混用,另外記錄陰影與背景物件的成本。

範例的範圍與後續擴充

本次提供五個階段的可閱讀教材與可執行整合範例。範例選擇基本的五零件角色、少量背景植栽、線條協作路徑及手機高度滑桿,方便讀者看清楚資料與工程結構。

第三方提示詞中的完整職業配件、頭頂 badge、每幀標籤避讓、三圈遠山、流動 Tube Shader、中英雙語與大數量背景樹,可在上述閉環穩定後逐項擴充。它們不應被記錄成這份教學已交付的功能。完整驗收結果以實際執行紀錄為準。

2026-10-22 舊版影片是資料與互動入門;本次簡易跟做 v2 改用短指令主線,並示範日夜與角色效果。此處保留較細的工程原理供選讀,不是初學者必須照寫的規格。

原始來源與 API 依據