exploded-view について
exploded-viewは、three.jsで機械アセンブリの分解表示を作るJavaScriptスキルです。ブラウザー向けの製品解説を作る開発者に適しており、段階的な分解、X線表示、断面表示、部品選択を備えています。
主な機能
- 01段階的な部品の分解
- 02引き出し線付き固定ラベル
- 03外装のX線表示
- 04外装の断面表示
- 05ホバーとクリックによる部品選択
活用シーン
- 01製品解説で組み立て順を示す
- 02外装の内側にある部品を見せる
- 03閲覧者が部品を識別・選択する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ moh4696/ open-3d-skills --skill exploded-viewインストール後、Claude Code で/exploded-viewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlassets/explode.jsassets/demo/index.htmlmotor.js詳細
分解図
機械を組み立てた順序で分解し、各部品がある場所に名前が付いている様子を見ると、仕組みを理解できます。このスキルはブラウザーでそれを実現します。部品は自然な方向に沿ってスライドして離れ、外殻は半透明になるか切り開かれ、ラベルはモデルに重なることなく部品に追従します。
ツール
| ファイル | 機能 |
|---|---|
assets/explode.js | Exploder(段階的な分解)、Labels(引き出し線付きの固定ラベル)、Xray、Section(外殻を貫くクリッピング平面)、Picker(ホバーとクリック) |
assets/demo/ | 完全なページです。コードで構築した誘導モーターを分解し、スライダー、X 線表示、断面表示を備えています。?explode=1、?cut=1、?xray=1 で状態を設定できます |
three.js が必要です(デモのインポートマップでは r169)。threejs-scene の手法でモデルを構築するか、GLB を読み込みます。
構築
1. モデルを部品ごとに構成する
分解図の単位は部品です。ひとまとまりで動く Group を指します。すべての部品を1つのアセンブリグループの直接の子にし、各部品に独自のマテリアルを設定します(X 線表示とホバーではマテリアルが変更されるため、共有マテリアルを使うと一度にすべての部品が変わってしまいます)。
GLB の場合は、読み込み時にグループを再構成します。シーンを走査し、ノード名に基づいてメッシュを名前付きの部品グループに親子付けします。親を付け替える際はワールド変換を保持します(group.attach(mesh))。
2. 各部品の移動方法を決める
部品ごとの設定は userData に保存します。
housing.userData = { shell: true, stage: 0, explode: [0, 0.32, 0] }; // lifts off first
rotor.userData = { stage: 2, explode: [0.42, 0, 0] }; // slides out along the shaft last
explode: [x, y, z]は、最大まで分解したときのオフセットです。指定しない場合、部品はアセンブリの中心から離れる方向に移動します(Exploderにaxisを渡すと、その軸に沿って距離に応じて移動します)。stageは移動の順序を指定します。ステージ 0 が最初に動き、後続のステージは前のステージが半分進んだ時点で開始します。整備士が分解するように、まずカバーと外殻、次に留め具とキャップ、最後に内部部品を取り外します。shell: trueは、外殻を X 線表示と断面カットの対象として指定します。
分解後の状態は、技術イラストのように配置します。主軸を1つ(シャフトや積層方向)決め、部品同士が重ならないように間隔を空け、大きな外殻は軸を外れて上方に移動させ、内部を見えるようにします。
const ex = new Exploder(assembly);
ex.set(t); // 0 assembled .. 1 exploded; ease toward a target each frame for slider input
3. 部品にラベルを付ける
const labels = new Labels(document.querySelector(".labels"), camera, canvas);
labels.add(rotor, "Rotor", { note: "turns in the magnetic field", anchor: [0.03, 0.07, 0] });
// every frame, after renderer.render():
labels.update();
ラベルは画面の左右端に2列で配置され、アンカーの上下順を保ちながら、重なりそうになると互いに離れます。各ラベルからアンカーポイントまで引き出し線が伸びます。ラベルは部品の分解に追従し、部品が非表示の場合やカメラの後ろにある場合は表示されません。各ラベルのアンカーは、メインビューから見える部品上の点(上端やシャフトの端など)に、部品のローカル座標で設定します。
.label、.label b、.label span、.leader と、それぞれの .focus バリエーションを CSS でスタイル設定します。画面の狭いスマートフォンではラベルを隠し、ホバーまたはタップした部品の名前を1つのキャプションに表示します。幅 390 px の画面では、モデルの横に2列のラベルを表示する余地がありません。
4. X 線表示と断面表示
const xray = new Xray(assembly); xray.set(true); // shells to 14% opacity, no depth write
renderer.localClippingEnabled = true;
const section = new Section(assembly, [0, 0, -1]); section.set(0); // cut the shells' front half away; null = off
断面平面で切るのは外殻だけなので、切り開かれた筐体の内部はそのまま保たれます。切断面を見せる図のような表示になります。切断面のマテリアルは両面描画に設定されるため、筐体の内側も見えます。
5. ピッキング
new Picker(canvas, camera, assembly.children, {
onHover: (part) => highlightLabelOf(part),
onPick: (part) => focusOn(part),
});
ホバーすると部品の発光色がわずかに変わり、ポインターカーソルに切り替わります。クリック時の動作として、部品のみを表示したり、カメラを部品に移動したり、説明を開いたりできます。
カメラとフレーミング
- 画面の形状に合わせてカメラをアセンブリにフィットさせ、分解量に応じて距離を調整します(デモの
autoDistance)。組み立て状態では近く、分解時には遠ざけます。訪問者がズームまたはオービット操作をしたら、自動調整を停止します。 OrbitControls.maxDistanceはフィット時の距離より大きく設定してください。そうしないと、コントロールによって気付かないうちに距離が制限され、スマートフォンでは一部が切れて表示されます。- 少し上から見下ろす斜め方向(デモでは方向 0.42、0.34、1)にすると、円筒形の機械の端面と側面を同時に表示できます。
スクロールに連動させる
scroll-film がフレームに対して行うように、スクロールの進行度をキーとホールドを使って ex.set() に割り当てます。イントロの読み進めに合わせて組み立て、ステージごとにキャプションを表示しながら段階的に分解し、完全に分解した状態を保持してから、断面を表示します。モデルはリアルタイムで動作するため、訪問者はいつでも停止して、視点を回転できます。
レンダリング
解説コンテンツには、空よりも製品写真のようなライティングが適しています。反射には RoomEnvironment の PMREM を使い、影付きのソフトなキーライトを ShadowMaterial の床に落とします。ACES トーンマッピングを使い、ページ独自の背景色をクリアカラーに設定します(不透明なキャンバスのデフォルトは黒です)。金属は roughness を 0.3〜0.45、metalness を 0.8〜0.95 にすると質感が伝わり、塗装部品には clearcoat を使います。
正確さ
対象が実在の製品なら、実際の部品名と正確な組み立て順を使い、内部の詳細のうち、解説用に簡略化したものはページ内の説明文に明記してください。誤った解説は、間違った内容を自信たっぷりに教えてしまいます。