{
  "exportedAt": "2026-07-15T13:17:25.306Z",
  "world": {
    "id": "53b305c5-1861-413e-aa52-f4923b6e56a5",
    "name": "已吉 IP 宇宙",
    "slug": "ezii-ip",
    "description": "個人 IP / 故事 / 角色 / 世界觀"
  },
  "cards": [
    {
      "id": "6eea5865-71d1-4644-a989-b58970b33dda",
      "title": "解析 Threads 炫炮網頁互動技法",
      "aliases": [],
      "type": "method",
      "typeName": "方法球",
      "content": {
        "text": "先說明一個重要前提:這個 Threads 帳號 (@aureliengmz) 本身**不是一個有特殊互動技法的網頁**——它就是普通的 Threads(React 寫的標準社群平台)。這個帳號是一個「策展帳號」,他每天**分享別人做的炫炮互動網頁 demo**。所以你看到的「技法」其實是貼文裡展示的、由其他創作者(Riyvir、amin_ankward 等人)做出來的作品。\n\n而且因為你目前是**登出狀態**,Threads 只讓我看到開頭幾則貼文,看不到全部。我只能看到兩個明確的技法。我也想去看他引用的原始碼 (`github.com/chenglou/pretext`),但那個網域不在我這次獲准訪問的範圍內,所以無法直接讀取原始碼。\n\n另外要坦白講:你說「複製我給的說明丟到 code 就一模一樣做好」——這點我做不到保證。那些作品(尤其 Three.js 的苔蘚 demo)是用 Blender geonodes + 自訂 shader 做了好幾天的成品,沒有公開完整原始碼,不可能靠一段說明就 100% 還原。我能給你的是**真實可用、能跑出類似效果的程式碼**,而不是「一模一樣」的承諾。\n\n以下是我從這個帳號實際看到的兩個技法:\n\n## 技法 1:Responsive Text(會自動擠壓/排版的響應式文字)\n\n貼文標題「the final boss of responsive text」,基於 `chenglou/pretext` 這個專案。核心概念是:文字會根據容器寬度,自動調整字級、行距、字距,讓排版永遠「剛剛好」填滿,像古書排版那樣。\n\n最簡單能丟進去就跑的版本,用純 CSS:\n\n```css\n.fluid-text {\n  /* clamp(最小值, 跟著視窗縮放的值, 最大值) */\n  font-size: clamp(1rem, 2.5vw + 0.5rem, 3rem);\n  line-height: 1.4;\n  /* 讓文字兩端對齊,像書本一樣 */\n  text-align: justify;\n  text-wrap: pretty; /* 避免最後一行只剩一個字 */\n  hyphens: auto;     /* 自動斷字 */\n}\n```\n\n如果你要更接近「字會自己填滿容器」那種效果,需要 JS 量測:\n\n```html\n<div class=\"fit-box\" style=\"width: 400px;\">\n  <span class=\"fit-text\">你的文字內容放這裡</span>\n</div>\n\n<script>\nfunction fitText(box) {\n  const text = box.querySelector('.fit-text');\n  let size = 8;\n  text.style.fontSize = size + 'px';\n  // 字一直放大,直到快要超出容器\n  while (text.scrollWidth <= box.clientWidth && size < 200) {\n    size++;\n    text.style.fontSize = size + 'px';\n  }\n  text.style.fontSize = (size - 1) + 'px';\n}\ndocument.querySelectorAll('.fit-box').forEach(fitText);\nwindow.addEventListener('resize', () =>\n  document.querySelectorAll('.fit-box').forEach(fitText)\n);\n</script>\n```\n\n## 技法 2:Three.js 互動式 3D 場景(苔蘚/自然 proximity 效果)\n\n貼文「style the moss industry」是 amin_ankward 用 Three.js + Blender geonodes 做的。原作者說它「基於基本數學和 proximity functions(距離函數)」。完整還原需要 3D 模型,但這裡給你一個**能直接跑、滑鼠靠近會有反應**的 Three.js 起手式:\n\n```html\n<script type=\"module\">\nimport * as THREE from 'https://cdn.skypack.dev/three@0.136';\n\nconst scene = new THREE.Scene();\nconst camera = new THREE.PerspectiveCamera(75, innerWidth/innerHeight, 0.1, 100);\ncamera.position.z = 5;\n\nconst renderer = new THREE.WebGLRenderer({ antialias: true });\nrenderer.setSize(innerWidth, innerHeight);\ndocument.body.appendChild(renderer.domElement);\n\n// 一堆粒子,模擬苔蘚顆粒\nconst count = 2000;\nconst geo = new THREE.BufferGeometry();\nconst pos = new Float32Array(count * 3);\nfor (let i = 0; i < count*3; i++) pos[i] = (Math.random()-0.5)*8;\ngeo.setAttribute('position', new THREE.BufferAttribute(pos, 3));\nconst points = new THREE.Points(geo,\n  new THREE.PointsMaterial({ color: 0x4a7c3a, size: 0.05 }));\nscene.add(points);\n\n// 記錄滑鼠位置 → 這就是 proximity 的來源\nconst mouse = new THREE.Vector2();\nwindow.addEventListener('pointermove', e => {\n  mouse.x = (e.clientX/innerWidth)*2 - 1;\n  mouse.y = -(e.clientY/innerHeight)*2 + 1;\n});\n\nfunction animate() {\n  requestAnimationFrame(animate);\n  // 整團跟著滑鼠輕輕轉動(proximity 反應)\n  points.rotation.y += (mouse.x*0.5 - points.rotation.y)*0.05;\n  points.rotation.x += (mouse.y*0.5 - points.rotation.x)*0.05;\n  renderer.render(scene, camera);\n}\nanimate();\n</script>\n```\n\n## 重點整理\n\n我從這個帳號實際看到的就是上面兩個技法(響應式文字 + Three.js proximity 互動)。其餘貼文因為登出看不到,沒辦法給你。\n\n如果你想要我抓到**完整清單**,有兩個方法:你先在瀏覽器裡登入 Threads,我再回來逐則往下捲、把每個技法都記錄下來;或是你告訴我特定哪一則貼文,我針對那個效果深入研究。\n\n你想用哪種方式繼續?另外,你比較想專攻「響應式文字」還是「Three.js 3D 互動」?我可以把其中一個做成更完整、更接近原作的版本給你。\n\n 我把這個帳號 (@aureliengmz) 推薦的每位作者都查完並交叉比對了。先講結論:他是個「策展帳號」,本身沒做技術,他推薦的是底下這幾位真正的創作者。以下是完整資訊。\n\n## 作者一覽表\n\n| 技法 | 原始作者 | 帳號/出處 | 來源類型 |\n|------|---------|----------|---------|\n| 響應式文字排版 (responsive text) | **Cheng Lou** | GitHub `@chenglou` / X `@_chenglou` | 開源函式庫 `pretext` |\n| 那則 demo 的視覺呈現 | **Riyvir** | X (Twitter) 上的 Riyvir | 個人 demo(基於 pretext) |\n| Three.js 苔蘚/自然互動 | **Amin Ankward** | Threads `@amin_ankward` / IG `amin_ankward` | 概念設計 (concept) |\n| 像素化 Three.js 效果 | **Samuel Jarry** | (由 gresfilip/Design Threads 轉述) | 開源,基於 Amin 的概念 |\n\n---\n\n## 作者一:Cheng Lou(響應式文字背後的真正技術)\n\n這是整個「final boss of responsive text」的核心。Aurelien 貼文寫的「based on the magic of » github.com/chenglou/pretext」就是指他。\n\n**身分(已查證):** Cheng Lou,人在加州,經歷非常硬——做過 ReactJS、ReasonML、ReScript、Messenger、Midjourney。他是知名開源作者,GitHub 有 9.6k followers,代表作包括 `react-motion`(21.9k stars 的動畫彈簧庫)。\n\n**他的 `pretext` 是什麼:** 一個純 JS/TypeScript 的「文字測量與排版」函式庫。重點突破在於——它**不碰 DOM 就能算出文字的高度與換行**,完全用瀏覽器的 canvas 字型引擎做純算術,避開了 `getBoundingClientRect`、`offsetHeight` 這類觸發瀏覽器 reflow(重排)的昂貴操作。這就是為什麼它能做到那種「文字完美填滿、不會 layout shift」的魔法效果。\n\n**最關鍵的功能**是它能算出「最緊的容器寬度」(shrink-wrap),也就是文字排起來剛好填滿、不浪費空間——這個能力以前 web 一直缺。\n\n**怎麼用(這段是官方 README 真實 API,可直接套):**\n\n```bash\nnpm install @chenglou/pretext\n```\n\n用法 1 — 純算高度,完全不碰 DOM:\n```js\nimport { prepare, layout } from '@chenglou/pretext'\n\nconst prepared = prepare('你的文字內容', '16px Inter')\nconst { height, lineCount } = layout(prepared, 320, 20)\n// 320 = 最大寬度, 20 = 行高。純算術,沒有 DOM reflow!\n// resize 時只要重跑 layout(),不要重跑 prepare()\n```\n\n用法 2 — 自己手動排每一行(可渲染到 Canvas/SVG/WebGL):\n```js\nimport { prepareWithSegments, layoutWithLines } from '@chenglou/pretext'\n\nconst prepared = prepareWithSegments('你的文字', '18px \"Helvetica Neue\"')\nconst { lines } = layoutWithLines(prepared, 320, 26)\nfor (let i = 0; i < lines.length; i++) {\n  ctx.fillText(lines[i].text, 0, i * 26)\n}\n```\n\n做「shrink-wrap / 平衡換行」(就是 demo 那種文字自動找最佳寬度):\n```js\nimport { walkLineRanges } from '@chenglou/pretext'\n\nlet maxW = 0\nwalkLineRanges(prepared, 320, line => { if (line.width > maxW) maxW = line.width })\n// maxW 就是「裝得下文字的最窄寬度」——這就是那個排版魔法的來源\n```\n\n**重要前提(官方有寫):** 它需要瀏覽器支援 `Intl.Segmenter` 和 Canvas 2D;在 macOS 上不要用 `system-ui`,要用具名字型(例如 Inter),否則測量會不準。\n\n---\n\n## 作者二:Riyvir(那則貼文的視覺 demo 製作者)\n\nAurelien 寫「wizard » Riyvir on x」,意思是那個你看到的具體畫面(古書排版那張)是 **Riyvir 在 X (Twitter) 上**做出來並發布的 demo,他用的底層技術就是上面 Cheng Lou 的 pretext。\n\n老實說:Riyvir 的出處是「X 上」,我這次沒辦法逐一確認他的完整帳號與原貼文(需要登入且 X 不在我已抓到的內容裡)。如果你要追他的原始碼,線索就是「在 X 搜尋 Riyvir + pretext」。技術核心已經在上面 Cheng Lou 那段給你了。\n\n---\n\n## 作者三:Amin Ankward(Three.js 苔蘚互動)\n\n**身分(已查證):** 帳號 `@amin_ankward`,自介寫「Concept & Design」,IG 是 `instagram.com/amin_ankward`。他的定位是**做互動概念 (concept)**,不一定每個都開源。他自己貼文說那個苔蘚作品:「透過 geonodes 製作,基於基本數學和 proximity functions(距離函數)」——也就是 Blender 的幾何節點 + 滑鼠距離運算。\n\n我也順手查到一個延伸資訊:他在 2025-8 還有另一個「pixelated effect(像素化效果)」的概念。\n\n可直接跑、滑鼠靠近會反應(proximity)的 Three.js 起手式:\n```html\n<script type=\"module\">\nimport * as THREE from 'https://cdn.skypack.dev/three@0.136';\n\nconst scene = new THREE.Scene();\nconst camera = new THREE.PerspectiveCamera(75, innerWidth/innerHeight, 0.1, 100);\ncamera.position.z = 5;\nconst renderer = new THREE.WebGLRenderer({ antialias: true });\nrenderer.setSize(innerWidth, innerHeight);\ndocument.body.appendChild(renderer.domElement);\n\nconst count = 2000;\nconst geo = new THREE.BufferGeometry();\nconst pos = new Float32Array(count * 3);\nfor (let i = 0; i < count*3; i++) pos[i] = (Math.random()-0.5)*8;\ngeo.setAttribute('position', new THREE.BufferAttribute(pos, 3));\nconst points = new THREE.Points(geo,\n  new THREE.PointsMaterial({ color: 0x4a7c3a, size: 0.05 }));\nscene.add(points);\n\nconst mouse = new THREE.Vector2();\naddEventListener('pointermove', e => {\n  mouse.x = (e.clientX/innerWidth)*2 - 1;\n  mouse.y = -(e.clientY/innerHeight)*2 + 1;\n});\n\nfunction animate() {\n  requestAnimationFrame(animate);\n  // proximity 反應:整團跟著滑鼠\n  points.rotation.y += (mouse.x*0.5 - points.rotation.y)*0.05;\n  points.rotation.x += (mouse.y*0.5 - points.rotation.x)*0.05;\n  renderer.render(scene, camera);\n}\nanimate();\n</script>\n```\n\n---\n\n## 作者四:Samuel Jarry(把 Amin 概念實作並開源的人)\n\n在 Amin 的個人頁我發現一個關鍵線索:有則貼文(由 **gresfilip / Design Threads** 發布)寫到——一個「用 ThreeJS 做的像素化效果」是 **Samuel Jarry 創作並開源 (open-sourced)**,而且是「受 Amin Ankward 的概念啟發」,要整合進 `thegistof.me` 這個網站。\n\n所以如果你想要**真正可拿來用的開源版**(而不是只有概念),Samuel Jarry 開源的那份才是你該找的程式碼源頭,關鍵字:「Samuel Jarry pixelated threejs open source / thegistof.me」。\n\n---\n\n## 必須對你誠實的兩件事\n\n第一,**「複製說明丟進去就一模一樣」這點我沒辦法保證**。pretext 我給你的是官方真實 API,可以直接 `npm install` 來用,這部分最接近「照做就行」。但 Amin 的苔蘚作品是 Blender geonodes + 自訂 shader 的成品,沒公開完整原始碼,我給的 Three.js 是「同類效果」而非 1:1 還原。\n\n第二,因為你**登出狀態**,Threads 只放出這幾則貼文就擋住了(顯示「登入以查看更多」)。上面這四位就是目前能看到的全部作者。如果你想要更完整的清單,你先在瀏覽器登入 Threads,我再回去逐則往下捲,把他推薦的每一位作者都抓給你。\n\n要不要我針對其中哪一位(例如直接幫你把 pretext 做成一個完整可跑的 HTML 範例頁)做深入版?"
      },
      "attributes": {
        "emoji": "✨",
        "steps": [
          "了解 Threads 帳號是「策展帳號」，分享他人作品。",
          "技法一：響應式文字，利用 CSS 的 `clamp` 或 JS 量測，讓文字自動調整大小與排版。",
          "技法二：Three.js 互動式 3D 場景，透過滑鼠移動觸發 Three.js 物件的旋轉或縮放，模擬自然互動效果。",
          "找出真正的創作者，例如 Cheng Lou (文字排版函式庫 pretext) 和 Amin Ankward (Three.js 互動概念)。",
          "注意：許多炫炮效果是創作者花費大量時間製作的成品，無法僅靠文字說明 100% 還原，但可提供類似效果的程式碼。"
        ],
        "origin": {
          "url": "https://cdn.skypack.dev/three@0.136",
          "type": "manual"
        },
        "status": "approved",
        "summary": "Threads 上分享的炫炮網頁互動，其實是其他創作者的作品。這份整理解析了其中兩種技法：能自動排版的文字，以及 Three.js 做的 3D 互動效果。",
        "category": "image",
        "category_color": "#7d8f5a",
        "category_emoji": "🎨",
        "category_label": "生圖/設計"
      },
      "tags": [
        "image",
        "approved"
      ],
      "isPinned": false,
      "wikiVisibility": false,
      "wikiSlug": null,
      "coverImage": null,
      "relations": [],
      "createdAt": "2026-06-11T05:25:47.564Z",
      "updatedAt": "2026-06-11T05:25:47.564Z"
    }
  ],
  "relations": [],
  "maps": []
}