Communitygithub.com

GA-MO/iso

以手寫 SVG + CSS/WAAPI 繪製動態等角投影產品插圖,呈現高級開發工具風格(圓角方塊、分層堆疊、帶光脈衝的線路、標籤、循環解說動作),無需動畫函式庫。

iso 是什麼?

這項技能讓 AI 代理能生成動態等角投影插圖,專門用於說明產品功能或工作流程。它透過一個名為 `iso` 的工具套件,無需依賴外部動畫函式庫,即可產出純 SVG 與 HTML 格式的動畫場景。使用者可以從多種預先定義的場景佈局與節拍模式中挑選,例如「物件抵達」、「光脈衝傳遞」或「網格填充」,並透過簡單的組合來敘述故事。此技能支援多種平台(如 Claude Code、Cursor 等),並提供豐富的範例場景(超過 60 個)與腳本工具,用於渲染、效能測試與對比度檢查,確保產出高品質的開發工具風格插圖。其核心概念是「場景建構器」與「執行時期引擎」,能實現響應式設計、視口感知的動畫播放(進入視野才播放、離開則暫停),並支援「減少動畫」的無障礙設定,非常適合製作登陸頁面、功能展示或互動式說明的視覺素材。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/GA-MO/isokit/tree/HEAD/skill

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

iso:動畫等角解說圖

一個場景在 6 到 14 秒的循環中講述一個產品故事:物件到來、光在它們之間傳遞、一次只亮起一個部分,然後循環回到第一個畫面。一個流程只有一種形狀。從節拍表中選擇故事需要的形狀:一個打開顯示其層次的盒子、兩個物件之間的交換、一個逐漸填滿的網格、一個旋轉選擇的堆疊,或透過懸停來抬起的拼貼。一切都是真實的 SVG 和 HTML 文字,隨其容器縮放,在螢幕外暫停,並在減少動畫模式下靜止。

此工具套件與此檔案位於同一目錄:

  • lib/iso.ts:Scene 建構器(投影、方塊、面、線路、脈衝、標籤、動作軌跡)、scene.exportSvg()、responsive() 和 lazyBox()。
  • lib/runtime.ts:使用 WAAPI 播放渲染後的場景,一旦場景的 40%(或半個螢幕高度,對於較高的場景)進入視野就開始其介紹,在螢幕外暫停,當它離開超過半個螢幕距離時移除其動畫,並在它返回前在同一畫格恢復,為減少動畫模式靜止,暴露 window.isoSeek(t)。
  • scripts/render.ts:將場景模組(預設導出 Page)渲染為一個獨立的 HTML 檔案,並內嵌執行時期。
  • scripts/shots.mjs:在選定的時間和寬度下對任何頁面截圖,並寫入 sheet.png。
  • scripts/check.ts:對磁碟上任一檔案進行嚴格的場景類型檢查(bun scripts/check.ts scene.ts)。
  • scripts/page-idle.mjs:讓一個包含多個場景的頁面完整滾動一次,然後在 0%、20%、35%、50%、60% 和 80% 的位置停止,並在 CPU 為 1x 和 4x 時印出主執行緒時間(node scripts/page-idle.mjs page=<url> width=393 dpr=3 scroll=4)。在包含超過幾個場景的頁面上執行它。
  • scripts/perf.mjs:在手機寬度下於 Chrome 中播放一個頁面,並對 CPU 進行節流(node scripts/perf.mjs page=<out.html> width=393 throttle=4 seconds=20),然後印出幀率、幀時間百分位數、延遲幀、長時間任務和主執行緒時間。在包含 30 個或更多移動物件的場景上執行它。
  • scripts/contrast.mjs、scripts/render-all.ts:在靜止畫格和另外四個時刻,測量渲染頁面中每個文字與其字形正後方像素的對比度,如果低於 4.5:1 則失敗(node scripts/contrast.mjs <out.html>;bun scripts/render-all.ts <dir> 先寫入所有目錄範例)。在每個場景完成前對其執行此檢查。
  • scripts/study-rive.mjs、scripts/compare-rive.mjs:可選工具,用於逐幀研究你自己的 .riv 動畫,並與工具套件場景進行比較。兩者都需要 runtime=<folder with canvas_advanced.mjs and rive.wasm>。
  • examples/:64 個針對虛構產品的場景,每個都是一個導出 example(標題、故事、提示、難度等級、類別、佈局、互動,以及 art:來自 art(compact, wide, breakpoint) 的緊湊和寬場景)和預設導出 Page 的檔案,因此 scripts/render.ts 可以渲染其中任何一個。spot 場景是單個小場景,art(compact)。hero.ts 導出 hero(一個 Art),material-gallery.ts 導出 galleries(每個材質系列一個 Art),每個都有預設導出 Page。examples/shared.ts 包含表面、顏色漸層、paints、字體和 fitX(),後者用於將標籤保持在場景內最窄的卡片中。

選擇最接近你故事的範例,並在繪製前閱讀:

範例難度展示內容
notifications.ts簡單最小化檔案:一個核心扇形展開到三個拼貼、脈衝、到達閃光與跳躍。請先閱讀此範例
ci-deploy.ts簡單一個套件沿著鏈條跳躍、落地壓縮、僅在結尾的狀態顏色
file-upload.ts簡單填充進度條的塊,然後複製擴散到邊緣點;空槽位的行進虛線
db-branching.ts簡單一個虛線幽靈變成實線,一個變更拼貼滑回並合併
service-map.ts簡單懸停:九個帶有 slab({ hover }) 的拼貼,懸停或點擊時顯示標籤,加上一個仍然講述故事的循環
auth-flow.ts中等一個直立的 panel() 手機、輸入文字、攜帶令牌的交接幽靈
etl-pipeline.ts中等來源拼貼沿著線路饋送到核心,線路隨之繪製,然後是一個填充與清空的網格;與它們所在的方塊分組的疊加層,使它們一起移動
queue-workers.ts中等一個由事件表驅動的槽佇列,建置過程會驗證事件表(無溢出、無從空佇列提取)
search-index.ts中等淺色頁面上的線條藝術拼貼、輸入查詢、符合條件的點亮、排名結果上升
feature-flags.ts中等遊玩:標籤中的真實 <button> 和一個內聯腳本,使用 seek 重播一個循環步驟
agent-tools.ts複雜一個帶有衛星的核心、請求和回覆脈衝、一個逐字輸入的答案卡片
checkout-payment.ts複雜一個帶有虛線返回路徑的步驟環,以及一個交叉淡化的狀態行
edge-cache.ts複雜同一個請求兩次:到來源的冷未命中,然後在邊緣的熱命中
observability.ts複雜三種訊號外觀(虛線、點、跨度)、帶有 heightTo 的 prism 條、警報與恢復
keycard-slot.ts、battery-charge.ts、tile-loader.ts、empty-box.ts點綴一個小型物件,用於功能列表、載入器或空狀態;一個在插槽邊緣裁剪的直立 panel() 卡片、heightTo 單元格、對角線下降波、行進虛線
sync-loop.ts、inbox-fill.ts、alert-stack.ts、table-scan.ts點綴壓扁到平面上的箭頭、一個玻璃前托盤、滑到一個堆疊上的卡片,帶有計數並騎在頂卡上的徽章、一個逐行滑動的透鏡
audit-ledger.ts、dns-resolve.ts、cron-jobs.ts簡單帶有印章的頁面堆疊、一次一跳並帶有回覆、觸發作業的撥號盤
vault-rotate.ts、firewall-filter.ts、zero-trust.ts中等使用插槽模式的密鑰交換、被拒絕的資料包彈回、每個請求都被蓋章
workload-scheduler.ts、autoscale.ts、health-check.ts中等從一個小型規則表中進行放置、為新節點騰出空間、一個被拉出並重新加入的節點
blue-green.ts、snapshot-restore.ts中等重新定位的線路、沿時間軸向後滑動的游標
embedding-clusters.ts、training-loss.ts、recs-rerank.ts、ab-test.ts中等點聚整合群、下降的 prism 條、重新排序的槽架、帶有勝出者的分割
data-erasure.ts、rag-answer.ts複雜一個請求扇形展開到六個系統並帶有計數器、檢索到的卡片飛入模型並逐字輸入答案
hero.ts複雜一個提示以 1、5、15 和 40 個的層級發展一個系統:轉盤旋轉進入和加權掉落、從下方滑出的輸出、彈出、一個伴隨網格填充掉入的池、無盡的請求、在靜止時朝向滑鼠的傾斜;透過 fill 和使用 <use> 的重複拼貼保持低成本;僅使用 SVG text(),因此 exportSvg() 可作用於它
funnel-live.ts、billing-cycle.ts、parcel-delivery.ts、test-shards.ts中等、複雜layout: 'wide':3:1 條狀從左到右閱讀(逐漸變窄的階段、一個無跳躍移動的月份條、運送盒子的車輛、在車道中競速並合併的碎片的
kanban-move.ts、stock-sync.ts、diff-merge.ts、refund-flow.ts簡單到複雜layout: 'diagonal':一個沿著一條等角軸線移動的卡片或令牌、閘門變綠、以第二種顏色沿相同路徑返回的退款
live-cursors.ts、two-approvals.ts、design-comments.ts、translate-six.ts簡單、中等layout: 'panels':彼此面對的直立 panel();輸入的游標、解鎖鎖頭的兩個勾選標記、別針和討論串、一個包含六種語言(帶有泰語和日語字體堆疊)的訊息
cms-publish.ts、sensor-gateway.ts、smart-home.ts、currency-convert.ts簡單、中等layout: 'radial':一個副本到五個頻道、讀數進入然後一層地板波出去、設備依次改變狀態、一個脈衝沿環形線路走一圈
ota-rollout.ts、build-cache.ts、calendar-booking.ts、load-slider.ts簡單到複雜layout: 'field':波穿過設備場,帶有暫停和重試、從依賴表計算出的快取命中、跳過衝突的會議;load-slider 是一個拖動控制項(真實的範圍輸入、滑鼠、觸控和按鍵),在環境流量持續移動時尋找循環
video-transcode.ts、image-resize.ts、fraud-gauge.ts、data-lineage.ts、drill-down.ts簡單到複雜layout: 'exploded':分離並編碼的版本、剝離的大小、累積超過一條線的風險層、向下穿過層次點亮的上游路徑;drill-down 透過一個真實按鈕,尋找該部分的循環片段,將一部分打開成其層次
materials-*.ts、material-gallery.ts六個系列(金屬、玻璃、自然、科技圖案、復古、生成式)中的 49 種側面飾面,作為 (scene) => Material 工廠,每個系列一個無標籤的圖庫。生成式飾面接受一個種子。複製一個飾面而非發明一個

一次性設定:cd <this dir>/scripts && bun install && bunx playwright install webkit(螢幕截圖使用已安裝的 Google Chrome 作為 Chromium)。類型檢查:scripts/node_modules/.bin/tsc -p <this dir>。

1. 繪製前先進行故事板

首先開啟 recipes.md。它包含所有經過測量的動作和構圖模式(到達、連接、流、比較、選擇、空閒、互動、緩動、表面),每個都有其數字和工具套件調用。從這些配方中組成故事,並保持它們的時間安排。

首先將故事寫成時間軸表格:觀眾應該理解什麼、展示它的 3 到 6 個節拍,以及對於每個節拍,哪個元素移動、如何移動、何時移動以及移動多久。每個節拍一個想法。一個需要一段文字來解釋的節拍,是兩個節拍或錯誤的圖片。

經過驗證的節拍形狀,附有測量時間:

節拍發生什麼事時間安排
到來碎片逐個落下,稍微過衝,然後穩定dropIn:每個 0.55 秒,83 毫秒間隔,46 像素下落
交接一個拼貼的幽靈輪廓從一個物件滑向另一個物件4 個幽靈,間隔 0.22 秒,每個 1.2 秒,ease.io
傳遞一個短光脈衝沿線路運行;目標在到達時閃爍270 像素/秒,脈衝約為線路的 0.12 至 0.16,上升 0.1 秒,淡出 0.6 秒
揭露層次一個實心盒子變成透明;內部層次逐個點亮,並附帶標籤開啟 0.23 秒,保持約 1 秒,關閉 0.2 秒,下一個在最後一個結束時開始
旋轉選擇一個堆疊向上移動一個槽位;活動卡片變成強調色每 3 秒移動 0.9 秒,慢速啟動,長時間緩出
填充與清空一個網格逐個拼貼填充,保持,然後回落到空進入時間隔 7 幀(0.12 秒),離開時間隔 2 幀
拉力當一條線路縮短或增長時,它所連接的盒子會沿線路方向被拉動約 6 像素,保持,然後緩慢恢復,使線路看起來有張力拉動 0.23 秒,保持 0.25 秒,返回 0.65 秒並帶有長時間緩出
懸停升起一個拼貼上升 16 像素並呈現其品牌顏色,其名稱出現slab({ hover }):開啟 270 毫秒,關閉 325 毫秒,ease.out

連接規則:一條線路僅在其兩端都在螢幕上時才顯示。連接到中途到來之物件的線路,會隨著其脈衝繪製自身(wire({ dash: '1 1' }),然後 at(id, 'strokeDashoffset', t, d, 1, 0, ease.linear)),並與它所連接的東西一起離開。切勿將這樣的線路放在介紹中。線路永遠不會越過一個盒子的頂面:在它所連接的物件之前添加它(因此它們會覆蓋它),並從盒子的邊緣開始,而不是中心。

循環規則:最後一幀等於第一幀。任何在循環期間變化的東西,都會在循環結束前恢復。僅在介紹中的動畫進入 intro();循環在介紹結束時開始,並且介紹必須以與循環開始相同的畫面結束。一個沒有介紹的元素,在介紹期間顯示循環的起始值,這是其循環片段的最後一個 to 值。

繪製順序是固定的:稍後添加的總是覆蓋先前添加的。會改變誰覆蓋誰的動畫(例如,一張卡片從堆疊頂部移動到底部)應繪製為槽位。每個元素都是一個槽位,移動一步並像其鄰居一樣淡出或重新著色,並且每個片段都從槽位的靜止值重新開始,因此所有槽位同時跳回,而畫面看起來相同。為每個槽位提供每個選項一個標籤,並交叉淡化在活動槽位旁顯示哪個。

2. 選擇佈局,然後先為手機構圖

每個範例在其 layout 中命名其構圖:wide(一個從左到右閱讀的長條;其寬場景大約為 3:1,例如 1200x400,斷點為 720,展示區將其顯示為全寬卡片)、diagonal(沿等角軸線的長行)、panels(彼此面對的直立 panel())、radial(一個核心,周圍有環形排列的東西)、field(從高處看到的許多拼貼;略陡的 ratio 有幫助)、exploded(垂直分離的層次)或 object(一個或兩個物件,用於功能列表或空狀態)。在繪製前選擇故事需要的佈局;當它們變化時,場景頁面閱讀起來更好。

一個觀眾可以遊玩的場景(interaction: 'play' | 'drag' | 'explore')會在 art() 的 head 中提供一個小型內聯模組腳本:label({ html }) 中的真實 <button> 或 <input type="range">、用於滑鼠和觸控的指標事件(拖動控制項上為 touch-action: none)、也支援按鍵、一個 MutationObserver 以綁定稍後掛載的場景、在觀眾操作時暫停循環並在空閒幾秒後恢復,以及一個在沒有輸入時仍然講述故事的循環(feature-flags.ts、load-slider.ts、drill-down.ts)。

展示頁面和登陸頁面是在手機上開啟的。構建兩個場景並使用 responsive(compact, wide) 包裝:

  • compact:約 390 寬,縱向或正方形(390x420 到 390x640)。故事從上到下堆疊。以 390 單位設計,因此大小為 13 的標籤在手機上為 13 像素。絕不低於 13。
  • wide:約 900 到 1200 寬,橫向,故事從左到右。

相關技能