Community画像github.com

habom2310/swarm-build

ウェブサイトに群衆アニメーションを追加します。名前と色が付いた複数のカーソルが領域ごとにボックスを描き、画像をブロックごとに構築したり、ライブページを再構築したりします。マルチプレイヤーやFigma風のカーソルをページに追加したい場合や、「swarm-build」という名前のスキルとして使用できます。素のHTMLやReact、Next.js、Vue、Svelte、Astroなどあらゆるフレームワークで動作します。

swarm-build とは?

swarm-buildは、画像やライブページを複数の名前付きカーソルが協力してブロックごとに構築するアニメーションを提供する軽量ライブラリです。依存関係がなく、約600行のESモジュールとCSSファイルのみで構成されています。Imageモードでは、画像の上にキャンバスを重ね、指定した領域をカーソルが順番に塗りつぶしていきます。Pageモードでは、HTMLに`data-swarm-block`属性を付与した要素を、カーソルが順番に再構築します。ヘッダーやカードなどのコンテナ要素は枠から埋められ、プレーンテキストの見出しや段落はタイプライターのように入力されます。スクロールに応じて画面外のブロックも順次処理されるため、ユーザーがページを読み進めるのに合わせてアニメーションが続きます。React、Vue、Svelte、Astroなど主要なフレームワークと互換性があり、`prefers-reduced-motion`設定も考慮されています。

対応~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/habom2310/swarm-build/tree/HEAD/skills/swarm-build

Installed? Explore more 画像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

プレビュー

スキル README より

swarm-build preview

ドキュメント

swarm-build は何をしますか?

swarm-buildは、依存関係のないESモジュール1つ(src/swarm-build.js、約600行)と、オプションのCSSファイル(src/swarm-build.css)で構成されています。 2つのモードがあります。

  • Imageモード、swarmBuild(img):<img>(またはCSS background-image を持つ要素)を白紙のキャンバスで覆い、各領域がカーソルによって矩形が引き出された後、ライブの W × H バッジと共にスイープインします。
  • Pageモード、swarmBuildPage("[data-swarm-block]"):ライブページのマークされた要素が非表示になり、その後カーソルがそれらを1つずつ再構築します。プレーンテキストのブロック(見出し、短い段落)はタイプライターで入力されます。他のブロック内にあるブロックは、親ブロックの完了を待ちます。画面外のブロックはスクロールして表示されるまで待機するため、群衆はページを読み進めるユーザーに追従します。

両モードとも、最後にカーソルは消え、ライブラリが行った変更はすべて元に戻されます。

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. Pageモード:ブロックをマークする

  1. ページのマークアップを読み、デザイナーが描くだろうブロック(ナビバー、ヒーロー見出し、ヒーロー段落、各ボタン、各カード、チャート、テーブル、フッター)を選びます。一般的なランディングページでは25から60個程度になります。
  2. 各ブロックに data-swarm-block を追加します。
    • コンテナ(カード)とその内部のテキスト(見出しや段落)をマークすると、「枠を先に、その後で中身を埋める」動作になります。
    • 内容がプレーンテキストの見出しや短い段落をマークすると、タイプライター入力されます。インラインマークアップ(リンク、<b>)を含む要素はスイープインします。
    • レイアウト専用のラッパー(グリッド、背景を持たないセクションなど)はスキップします。これらを非表示にすると、内部のすべてが一度に非表示になります。
  3. 訪問者がすぐに必要とする固定またはスティッキーなUI(Cookieバナーやチャットウィジェットなど)はマークしないでください。
  4. コンテンツがDOMに存在した後に呼び出します:
import { swarmBuildPage } from "./lib/swarm-build/swarm-build.js";
swarmBuildPage("[data-swarm-block]", { speed: 1.5 });

スクリプト実行前にブロックを非表示にするには(完成したページが一瞬表示されるのを防ぐ)、各ブロックに data-swarm-pending も追加し、CSSファイルをインクルードします。

2b. Imageモード:領域を選択する

領域は何がどの順序で構築されるかを決定します。 適切な領域がアニメーションを意図的に見せます。この手順は省略しないでください。

  1. 画像を開いて見てください(画像ファイルを読むか、ページのスクリーンショットを撮ってください)。
  2. デザイナーが描くだろう意味のあるブロックを6~15個リストアップします:ナビゲーションレール、ヘッダー、検索バー、カード、チャート、リスト、フッター。
  3. 各ブロックを画像の幅と高さのパーセンテージ(0~100)で x y w h として記述します。ピクセルサイズから測定します:x = left / imageWidth * 100。
  4. 人が画面を構築する順序に並べます:クローム(レール、ヘッダー)、次にコンテンツを上から下へ。
  5. 小さな隙間は残しておきます。どの領域もカバーしない部分は、最後にキャンバスがフェードアウトするときに表示されます。そのため、すべてのピクセルを領域でカバーする必要はありません。

画像に 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とスマートフォン)で1つの群衆を共有することもできます:swarmBuild([ipadImg, phoneImg])。

4. オプション

オプションデフォルト用途
regions(ターゲットごと)data-swarm-regions、次に汎用何をどの順序で構築するか
agents6つの組み込みの名前と色[{ name, color, text }]、サイトのパレットとオーディエンスに合わせる
speed12 で所要時間が半分になる(10~15領域で約6~8秒、1の場合)
start"visible""now" にすると画像がスクロールして表示されるのを待たずに即座に開始
canvas"#fff"未構築のキャンバスの色。スクリーンショットの背景に合わせる
zIndex2147483000固定カーソルレイヤーの重なり順。モーダルやヘッダーを前面に表示する必要がある場合は下げる
onDoneなしビルドが完了するか finish() が呼び出されたときに1回呼び出される
typeSpeed(Pageモード)1タイプライター入力の速度。2 で2倍速

戻り値には finished、finish()、destroy() があります:

  • finished は、群衆の終了方法に関わらず常に解決されるPromise。
  • finish() は完成した画像にジャンプし、onDone が実行されます。
  • destroy() は即座にすべてを削除し、onDone は実行されません。アンマウント時に呼び出します。
  • setSpeed(n) は実行中に速度を変更します。

Pageモードでは start のデフォルトは "now" になり、Imageモードでは "visible" になります。

5. 守るべきルール

  • data-swarm-pending とCSSファイルにより、画像はスクリプトが開始するまで非表示に保たれるため、完成した状態が一瞬表示されることはありません。スクリプトが実行されなかった場合、CSSは4秒後に画像を表示します。画像がページのLCP要素であり、読み込み時間がエフェクトよりも重要な場合は、属性を外してください。
  • 動きの減少設定(prefers-reduced-motion: reduce)は、完成した画像を表示し、アニメーションは行いません。これを上書きしないでください。
  • カーソルはページの上に固定された、全ビューポートのレイヤーに配置されます(pointer-events: none)。
  • 実行中、ライブラリは画像の直後、画像の親要素内にオーバーレイを挿入します。親がstaticだった場合、position: relative も設定されます。両方とも最後に元に戻されます。
    • 画像には独自のブロックレベル親要素(<div> や <figure> など)を指定してください。<a> や <picture> などのインライン親要素ではオーバーレイの位置がずれる可能性があります。
    • :last-child や Tailwind の space-y-* などの兄弟CSSは、オーバーレイが存在する間に一時的に変化する可能性があります。
  • 画像は画像のcontent boxに引き伸ばされたCSS背景としてコピーされます。画像のボーダーやパディングは問題ありませんが、object-fit: cover や contain によるトリミングは再現されません。
  • 厳格なCSPやTrusted Typesの下では変更は不要です。ライブラリはすべての要素をDOM呼び出しで構築し、CSSOMを通じてスタイルを設定し、innerHTML、<style>、インラインスクリプトは使用しません。画像URLは img-src で許可されている必要があります。

6. 確認

  1. ページを読み込み、1回の完全なビルドを確認します。各ボックスが画像の実際のUIブロックに配置され、空きスペースや2つのブロックにまたがっていないことを確認します。
  2. スマートフォン幅(375px)で確認します。バッジや名前タグは固定サイズのため、非常に小さな画像では密集して見える可能性があります。その場合は、より少ない、より大きな領域を使用します。
  3. OSまたはブラウザの開発者ツールで動きの減少設定をオンにします:画像はカーソルなしで即座に表示される必要があります。
  4. コンソールにエラーがないこと、また完了後に aria-hidden の群衆要素がDOMに残っていないことを確認します。

関連スキル