swarm-build 是做什麼的?
swarm-build 是一個無依賴的 ES 模組(src/swarm-build.js,約 600 行)加上一個可選的 CSS 檔案(src/swarm-build.css)。
它提供兩種模式:
- 圖片模式,
swarmBuild(img):一個空白畫布覆蓋在<img>(或具有 CSSbackground-image的元素)上,每個區域會先由游標拖曳出一個方框,並顯示即時的W × H標籤,然後該區域才掃入顯現。 - 頁面模式,
swarmBuildPage("[data-swarm-block]"):標記的頁面元素先消失,然後游標逐一重建它們。純文字區塊(標題、短段落)會以打字機方式輸入。巢狀在其他區塊內的區塊會等待其父區塊完成。折疊以下的區塊會等到它們滾入視野才開始,因此 swarm 會跟隨讀者向下移動。
兩種模式結束後,游標都會離開,函式庫所做的所有變更都會被還原。
1. 安裝
將此儲存庫中的 src/swarm-build.js、src/swarm-build.d.ts 和 src/swarm-build.css 複製到專案中(例如 lib/swarm-build/),並使用相對路徑導入它們。
沒有依賴關係,也不需要建置步驟。
僅當 npm view swarm-build 顯示套件已發布時:npm install swarm-build,然後 import { swarmBuild } from "swarm-build" 和 import "swarm-build/style.css"。
2a. 頁面模式:標記區塊
- 閱讀頁面的 markup,挑選設計師會繪製的區塊:導覽列、英雄區標題、英雄區段落、每個按鈕、每張卡片、圖表、表格、頁尾。一個典型的登陸頁面約有 25 到 60 個區塊。
- 為每個區塊加上
data-swarm-block。- 標記容器(如卡片)及其內部的文字(標題和段落),以達到「先畫框架,再填入內容」的效果。
- 標記內容為純文字的標題和短段落:這些會以打字機方式輸入。包含行內標記(如連結、
<b>)的元素則會以掃入方式顯現。 - 跳過僅用於佈局的包裝器(如網格、沒有自己背景的區段)。隱藏它們會同時隱藏內部所有內容。
- 不要標記訪客需要立即使用的固定或黏性 UI,例如 Cookie 橫幅或聊天 widget。
- 在內容進入 DOM 後呼叫它:
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });
若要在腳本執行前隱藏區塊(避免閃現完成後的頁面),也為每個區塊加上 data-swarm-pending 並引入 CSS 檔案。
2b. 圖片模式:選擇區域
區域決定了建構的內容和順序。 好的區域能讓動畫看起來有設計感,所以請不要跳過這個步驟。
- 打開圖片並觀察它(讀取圖片檔案,或對頁面截圖)。
- 列出 6 到 15 個設計師會繪製的有意義區塊:導航欄、頁首、搜尋列、卡片、圖表、清單、頁尾。
- 將每個區塊寫為相對於圖片寬度和高度的百分比(0 到 100)的
x y w h。從像素尺寸測量:x = left / imageWidth * 100。 - 按照人們建構畫面的順序排列:先畫 chrome(導航欄、頁首),然後內容從上到下。
- 留一些小空隙。沒有任何區域覆蓋的部分會在最後畫布淡出時出現,因此區域不需要覆蓋每一個像素。
將它們作為 data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, ..." 放在圖片上,或在 JavaScript 中傳遞 regions: [{ x, y, w, h }]。
沒有指定區域時,函式庫會使用通用的側邊欄、頁首和卡片佈局,這通常與圖片不匹配。
3. 接入使用
純 HTML:
<link rel="stylesheet" href="/lib/swarm-build/swarm-build.css" />
<img src="/shot.png" alt="..." width="1200" height="800"
data-swarm-pending
data-swarm-regions="0 0 18 100, 21 3.5 47 5.5, 21 13 24 16" />
<script type="module">
import { swarmBuild } from "/lib/swarm-build/swarm-build.js";
swarmBuild(document.querySelector("img[data-swarm-regions]"));
</script>
React 或 Next.js(客戶端元件):
"use client";
import { useEffect, useRef } from "react";
import { swarmBuild } from "@/lib/swarm-build/swarm-build.js";
export function BuiltImage(props: React.ComponentProps<"img"> & { regions: string }) {
const ref = useRef<HTMLImageElement>(null);
useEffect(() => {
const swarm = swarmBuild(ref.current!);
return () => swarm.destroy();
}, []);
const { regions, ...img } = props;
return <img ref={ref} {...img} data-swarm-pending="" data-swarm-regions={regions} />;
}
對於 Vue、Svelte 或 Astro,做同樣的事:在掛載後呼叫 swarmBuild(el),並在卸載時呼叫 destroy()。
多張圖片(例如一台 iPad 和一支手機)可以共用一個 swarm:swarmBuild([ipadImg, phoneImg])。
4. 選項
| 選項 | 預設值 | 用途 |
|---|---|---|
regions(每個目標) | data-swarm-regions,然後通用 | 要建構的內容及順序 |
agents | 6 個內建名稱和顏色 | [{ name, color, text }],匹配網站的色調和受眾 |
speed | 1 | 2 將持續時間減半(10 到 15 個區域時,約 6 到 8 秒) |
start | "visible" | "now" 立即開始,而不是等到圖片滾入視野 |
canvas | "#fff" | 未建構畫布的顏色;與截圖的背景色匹配 |
zIndex | 2147483000 | 固定游標層的堆疊順序;如果 modal 或頁首必須保持在頂層,則降低它 |
onDone | 無 | 建構完成或呼叫 finish() 時呼叫一次 |
typeSpeed(頁面模式) | 1 | 打字文字的速度;2 打字速度加倍 |
回傳值包含 finished、finish() 和 destroy():
finished是一個始終會 resolve 的 Promise,無論 swarm 如何結束。finish()跳轉到完成後的圖片,onDone會執行。destroy()立即移除所有內容,onDone不會執行。在卸載時呼叫它。setSpeed(n)在執行時改變速度。
在頁面模式中 start 預設為 "now";在圖片模式中預設為 "visible"。
5. 應遵守的規則
data-swarm-pending加上 CSS 檔案可在腳本執行前保持圖片隱藏,因此它不會先閃現完成狀態。如果腳本從未執行,CSS 會在 4 秒後顯示圖片。當圖像是頁面的 LCP 元素且載入時間比效果更重要時,請省略該屬性。- 減少動畫設定(
prefers-reduced-motion: reduce)會直接顯示完成的圖片,且永遠不進行動畫。請勿覆寫此設定。 - 游標位於頁面上方一個固定、全視圖的圖層中(
pointer-events: none)。 - 在執行期間,函式庫會在圖片之後、圖片的父元素內部插入一個疊加層。如果父元素原本是靜態定位,它也會為其設定
position: relative。兩者都會在結束時被還原。- 為圖片提供一個獨立的區塊級父元素,例如
<div>或<figure>。行內父元素如<a>或<picture>可能會導致疊加層錯位。 - 像
:last-child或 Tailwindspace-y-*這類相鄰 CSS 可能會在疊加層存在時短暫改變。
- 為圖片提供一個獨立的區塊級父元素,例如
- 圖片會以 CSS 背景的方式複製,並拉伸至圖片的內容框。圖片上的邊框和內距沒有問題,但
object-fit: cover或contain裁剪不會被重現。 - 在嚴格的 CSP 或 Trusted Types 下不需要任何變更:函式庫使用 DOM 呼叫建構每個元素,透過 CSSOM 設定樣式,並且不使用
innerHTML、<style>或行內腳本。圖片 URL 必須被img-src允許。
6. 驗證
- 載入頁面並觀看一次完整的建構過程。每個方框都應落在圖片的真實 UI 區塊上,而不是空白區域或跨越兩個區塊。
- 檢查手機寬度(375px)。徽章和名稱標籤有固定大小,因此非常小的圖片可能會感覺擁擠;在那裡使用更少、更大的區域。
- 在作業系統或瀏覽器開發者工具中開啟減少動畫設定:圖片必須立即顯示,沒有游標。
- 檢查主控台是否有錯誤,並確認在動畫完成後 DOM 中沒有遺留
aria-hidden的 swarm 元素。
