spline-interactive
ブラウザ上で動作するビジュアル3Dデザインツールで、アニメーションやWeb向けエクスポートに対応しています。コードを書かずに3Dシーンを作成したい場合、インタラクティブなWeb体験のデザイン、3D UIのプロトタイピング、ReactへのエクスポートやSplineシーンの組み込みなどの作業に活用できます。コードよりもビジュアルツールを好むデザイナー向けのThree.js代替手段として、ノーコード3D・ステートベースのインタラクション・ビジュアル3Dエディタに関するタスクでトリガーされます。
description の原文を見る
Browser-based 3D design tool with visual editor, animation, and web export. Use this skill when creating 3D scenes without code, designing interactive web experiences, prototyping 3D UI, exporting to React/web, or building designer-friendly 3D content. Triggers on tasks involving Spline, no-code 3D, visual 3D editor, 3D animation, state-based interactions, React Spline integration, or scene export. Alternative to Three.js for designers who prefer visual tools over code.
SKILL.md 本文
Spline Interactive - ブラウザベースの 3D デザインとアニメーション
概要
Spline はブラウザベースの 3D デザイン・アニメーション プラットフォームで、クリエイターがコードや専門知識を必要とせずにインタラクティブな 3D エクスペリエンスを構築できます。複数のプラットフォーム向けに 3D シーンを設計、アニメーション化、エクスポートするための協調的なビジュアルエディタを提供します。
主な機能:
- パラメトリック シェイプ、押し出し、ブール演算によるビジュアル 3D モデリング
- タイムラインコントロール付きのステートベースアニメーション システム
- インタラクティブなイベント システム (マウス、キーボード、衝突、スクロール)
- 複数のエクスポート オプション (React コンポーネント、Web コード、パブリック URL)
- リアルタイム コラボレーション機能とチーム ライブラリ
- AI による生成機能 (テキストからの 3D、テクスチャ、スタイル転送)
- 内蔵の物理演算とパーティクル システム
このスキルを使用する場合:
- Three.js コードを書かずに 3D Web エクスペリエンスを作成する
- インタラクティブな製品紹介やコンフィグレータを設計する
- 3D UI/UX コンセプトをビジュアルにプロトタイピングする
- 3D 要素を含むマーケティング ページを構築する
- デザイナーと 3D コンテンツで協力する
- React または バニラ JS 統合用にシーンをエクスポートする
代替手段:
- Three.js (threejs-webgl): コードファーストのアプローチを好み、最大限の制御が必要な開発者向け
- Babylon.js (babylonjs-engine): 内蔵物理演算を備えたゲーム向けプロジェクト
- React Three Fiber (react-three-fiber): JSX で 3D を構築したい React 開発者向け
コアコンセプト
1. シーン構造
Spline はプロジェクトを以下を含むシーンに整理します:
- オブジェクト: 3D モデル、シェイプ、テキスト、画像
- ライト: 方向光、ポイントライト、スポットライト
- カメラ: オービタル、透視投影、正投影
- イベント: インタラクション トリガー
- ステート: アニメーション キーフレーム
2. コンポーネント システム
以下のような再利用可能な要素:
- 任意のオブジェクトまたはグループから作成
- 複数回のインスタンス化
- すべてのインスタンス間での更新
- インスタンスごとのオーバーライド
3. ステートベース アニメーション
アニメーションはステート間の遷移として定義されます:
- デフォルト ステート: 初期の外観
- 追加ステート: ターゲット外観
- イベント: ステート遷移の原因
- トランジション: 期間、イージング、プロパティ
4. インタラクティビティ モデル
イベント駆動型のシステム:
- イベント: ユーザーのアクションまたはシーン トリガー
- 条件: ロジック ゲート (if/else)
- アクション: ステート変更、オーディオ、シーン切り替え
- 変数: API またはユーザー入力からの動的データ
5. エクスポート オプション
複数のデプロイ方法:
- パブリック URL: 直接共有可能なリンク
- コード エクスポート: React コンポーネントまたはバニラ JS
- Spline ビューアー: 埋め込み iframe
- セルフホスト: 独立してダウンロードしてホスト
一般的なパターン
パターン 1: 基本的な React 統合
ユースケース: React アプリケーションに Spline シーンを埋め込む
実装:
# インストール
npm install @splinetool/react-spline @splinetool/runtime
import Spline from '@splinetool/react-spline';
export default function Hero() {
return (
<div style={{ width: '100%', height: '600px' }}>
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
</div>
);
}
重要なポイント:
- シーン URL は Spline エクスポート ダイアログから取得
- コンポーネントは親コンテナに合わせて拡大縮小
- 自動的にロードとレンダリングを処理
パターン 2: イベント ハンドリングとオブジェクト インタラクション
ユースケース: 特定のオブジェクトへのユーザー クリックに応答
実装:
import Spline from '@splinetool/react-spline';
export default function InteractiveScene() {
function onSplineMouseDown(e) {
// クリックされたオブジェクトがボタンかチェック
if (e.target.name === 'Button') {
console.log('ボタンがクリックされました!');
// オブジェクトのプロパティを取得
console.log('位置:', e.target.position);
console.log('回転:', e.target.rotation);
console.log('スケール:', e.target.scale);
}
}
function onSplineMouseHover(e) {
if (e.target.name === 'Button') {
console.log('ボタンの上にホバーしています');
}
}
return (
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onSplineMouseDown={onSplineMouseDown}
onSplineMouseHover={onSplineMouseHover}
/>
);
}
利用可能なイベント ハンドラー:
onSplineMouseDown- オブジェクトへのマウス押下onSplineMouseUp- マウス リリースonSplineMouseHover- オブジェクトの上にマウスonSplineKeyDown- キー押下onSplineKeyUp- キー リリースonSplineStart- シーンがロードされて開始onSplineLookAt- カメラ見つめイベントonSplineFollow- カメラ フォロー イベントonSplineScroll- スクロール イベント
パターン 3: プログラム的なオブジェクト制御
ユースケース: React コードからオブジェクトのプロパティを変更
実装:
import { useRef } from 'react';
import Spline from '@splinetool/react-spline';
export default function ProductViewer() {
const cube = useRef();
const splineApp = useRef();
function onLoad(spline) {
// Spline インスタンスを保存
splineApp.current = spline;
// 名前でオブジェクトを検索
const obj = spline.findObjectByName('Product');
// または ID で検索
// const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E');
cube.current = obj;
}
function rotateProduct() {
if (cube.current) {
// Y 軸の周りに 45 度回転
cube.current.rotation.y += Math.PI / 4;
}
}
function changeColor() {
if (cube.current) {
// マテリアル カラーを変更 (16 進数カラー)
cube.current.material.color.set(0xff6b6b);
}
}
function moveProduct() {
if (cube.current) {
cube.current.position.x += 50;
cube.current.position.y += 10;
}
}
return (
<div>
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onLoad={onLoad}
/>
<div style={{ position: 'absolute', top: 20, left: 20 }}>
<button onClick={rotateProduct}>回転</button>
<button onClick={changeColor}>色を変更</button>
<button onClick={moveProduct}>移動</button>
</div>
</div>
);
}
変更できるオブジェクト プロパティ:
position- { x, y, z }rotation- { x, y, z } (ラジアン)scale- { x, y, z }material.color- カラー 16 進数値visible- ブール値
パターン 4: Spline アニメーションのトリガー
ユースケース: React から Spline で定義されたアニメーションをトリガー
実装:
import { useRef } from 'react';
import Spline from '@splinetool/react-spline';
export default function AnimatedCard() {
const splineApp = useRef();
function onLoad(app) {
splineApp.current = app;
}
function triggerHoverAnimation() {
// 'Card' オブジェクトに mouseHover イベントを発行
splineApp.current.emitEvent('mouseHover', 'Card');
}
function triggerClickAnimation() {
// 'Button' オブジェクトに mouseDown イベントを発行
splineApp.current.emitEvent('mouseDown', 'Button');
}
function reverseAnimation() {
// アニメーションを逆再生
splineApp.current.emitEventReverse('mouseHover', 'Card');
}
return (
<div>
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onLoad={onLoad}
/>
<button onClick={triggerHoverAnimation}>ホバー エフェクト</button>
<button onClick={triggerClickAnimation}>クリック エフェクト</button>
<button onClick={reverseAnimation}>逆再生</button>
</div>
);
}
利用可能なイベント タイプ:
mouseDown- マウス押下mouseHover- ホバー エフェクトmouseUp- マウス リリースkeyDown- キー押下keyUp- キー リリースstart- スタート イベントlookAt- カメラを見つめるfollow- カメラをフォロー
パターン 5: Next.js 統合と SSR
ユースケース: Next.js でサーバーサイド レンダリングの利点を得ながら Spline を使用
実装:
// app/page.js (Next.js 13+ App Router)
import Spline from '@splinetool/react-spline/next';
export default function Home() {
return (
<main>
<div style={{ width: '100vw', height: '100vh' }}>
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
</div>
</main>
);
}
利点:
- SSR 中にプレースホルダー画像を表示
- より高速な読み込み感覚
- フォールバック コンテンツを備えた SEO の向上
パターン 6: パフォーマンス向けの遅延読み込み
ユースケース: 必要になるまで Spline の読み込みを遅延
実装:
import React, { Suspense } from 'react';
// Spline を動的にインポート
const Spline = React.lazy(() => import('@splinetool/react-spline'));
export default function LazyScene() {
return (
<div>
<h1>マイ ページ コンテンツ</h1>
<Suspense fallback={<div>3D シーンを読み込み中...</div>}>
<div style={{ width: '100%', height: '500px' }}>
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
</div>
</Suspense>
<p>下部のさらなるコンテンツ</p>
</div>
);
}
利点:
- 初期バンドル サイズを削減
- ページ読み込みパフォーマンスを向上
- カスタム読み込み UI を表示
パターン 7: レスポンシブな Spline シーン
ユースケース: Spline シーンを異なる画面サイズに対応させる
実装:
import Spline from '@splinetool/react-spline';
import { useState, useEffect } from 'react';
export default function ResponsiveScene() {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768);
};
checkMobile();
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}, []);
return (
<div style={{
width: '100%',
height: isMobile ? '400px' : '600px'
}}>
<Spline
scene={
isMobile
? "https://prod.spline.design/YOUR-MOBILE-SCENE/scene.splinecode"
: "https://prod.spline.design/YOUR-DESKTOP-SCENE/scene.splinecode"
}
/>
</div>
);
}
代替アプローチ (単一シーン):
import Spline from '@splinetool/react-spline';
import { useRef, useEffect } from 'react';
export default function ResponsiveScene() {
const splineApp = useRef();
function onLoad(app) {
splineApp.current = app;
adjustForScreenSize();
}
function adjustForScreenSize() {
if (!splineApp.current) return;
const camera = splineApp.current.findObjectByName('Camera');
const isMobile = window.innerWidth < 768;
if (isMobile) {
// モバイルでズームアウト
splineApp.current.setZoom(0.7);
// カメラ位置を調整
camera.position.z = 1500;
}
}
useEffect(() => {
window.addEventListener('resize', adjustForScreenSize);
return () => window.removeEventListener('resize', adjustForScreenSize);
}, []);
return (
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onLoad={onLoad}
/>
);
}
統合パターン
Three.js との統合 (threejs-webgl)
高度なユースケースでは、Spline 設計のアセットと Three.js コードを組み合わせます:
- Spline からエクスポート: GLTF/GLB エクスポートを使用
- Three.js にインポート: GLTFLoader を使用してロード
- コードで拡張: カスタム シェーダー、物理演算、またはエフェクトを追加
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const loader = new GLTFLoader();
loader.load('spline-model.glb', (gltf) => {
scene.add(gltf.scene);
// カスタム動作を追加
});
GSAP との統合 (gsap-scrolltrigger)
スクロール時に Spline アニメーションをトリガー:
import { useEffect, useRef } from 'react';
import Spline from '@splinetool/react-spline';
import gsap from 'gsap';
import ScrollTrigger from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
export default function ScrollAnimated() {
const splineApp = useRef();
function onLoad(app) {
splineApp.current = app;
ScrollTrigger.create({
trigger: '.scene-container',
start: 'top center',
onEnter: () => {
app.emitEvent('mouseHover', 'Product');
}
});
}
return (
<div className="scene-container">
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onLoad={onLoad}
/>
</div>
);
}
Framer Motion との統合 (motion-framer)
Spline が 3D を処理している間にコンテナをアニメーション:
import { motion } from 'framer-motion';
import Spline from '@splinetool/react-spline';
export default function AnimatedContainer() {
return (
<motion.div
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
style={{ width: '100%', height: '600px' }}
>
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
</motion.div>
);
}
パフォーマンス最適化
1. オンデマンド レンダリングを有効化
フレームごとではなく、シーン変更時のみレンダリング:
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
renderOnDemand={true} // デフォルトは true
/>
2. Spline エディターでシーンを最適化
Spline内:
- ポリゴン数を削減 (decimation を使用)
- テクスチャを圧縮 (解像度を下げる、PNG 上で JPG を使用)
- ライトを制限 (最大 2~3 個)
- 可能な場合は単純なマテリアルを使用
- 遠いオブジェクトに LOD (Level of Detail) を有効化
3. 重いシーンを遅延読み込み
パターン 6 に示すように React.lazy() を使用
4. クリティカル シーンをプリロード
import { useEffect } from 'react';
import Spline from '@splinetool/react-spline';
export default function PreloadedScene() {
useEffect(() => {
// シーン アセットをプリロード
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = 'https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode';
document.head.appendChild(link);
}, []);
return (
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
);
}
5. モバイル最適化
- 詳細度が低い別のモバイル シーンを作成
- モバイルでキャンバス解像度を低下
- シャドウとリフレクションを無効化
- より単純なマテリアルを使用
<Spline
scene={isMobile ? mobileSceneUrl : desktopSceneUrl}
style={{
width: '100%',
height: isMobile ? '300px' : '600px'
}}
/>
一般的な落とし穴と解決策
落とし穴 1: シーンが読み込まれない
問題: Spline コンポーネントがレンダリングされるがシーンが表示されない
解決策:
// ❌ 誤り: 無効なシーン URL
<Spline scene="my-scene.splinecode" />
// ✅ 正解: Spline エクスポートからのフル URL
<Spline scene="https://prod.spline.design/KFonZGtsoUXP-qx7/scene.splinecode" />
// エラーをチェック
function onLoad(app) {
console.log('シーンが正常に読み込まれました', app);
}
<Spline scene={sceneUrl} onLoad={onLoad} />
また確認:
- Spline エディターでシーンが公開されている
- ネットワーク タブにファイルの正常なダウンロードが表示されている
- コンソールに CORS エラーがない
落とし穴 2: 再レンダリング後にオブジェクト参照が失われる
問題: コンポーネント更新後にオブジェクト参照が undefined になる
解決策:
// ❌ 誤り: 適切な参照なしでオブジェクトを保存
let myObject;
function onLoad(spline) {
myObject = spline.findObjectByName('Cube'); // 再レンダリングで失われる
}
// ✅ 正解: React refs を使用
const myObject = useRef();
function onLoad(spline) {
myObject.current = spline.findObjectByName('Cube');
}
落とし穴 3: モバイルでのパフォーマンス問題
問題: モバイル デバイスでシーンが遅く実行される
解決策:
// Spline エディターでモバイル最適化版を作成
// - より少ないポリゴン (< 50k トライアングル)
// - より小さいテクスチャ (512x512 以下)
// - シャドウやリフレクションなし
// - よりシンプルなマテリアル
// 適切なバージョンを読み込み
const isMobile = window.innerWidth < 768;
const sceneUrl = isMobile
? 'https://prod.spline.design/MOBILE-SCENE/scene.splinecode'
: 'https://prod.spline.design/DESKTOP-SCENE/scene.splinecode';
<Spline scene={sceneUrl} renderOnDemand={true} />
落とし穴 4: イベントが発火しない
問題: クリック またはホバー イベントがトリガーされない
解決策:
// ❌ 誤り: 間違ったイベント名を使用
<Spline onMouseDown={handler} /> // Spline prop ではない
// ✅ 正解: Spline イベント props を使用
<Spline onSplineMouseDown={handler} />
// また、Spline エディターでオブジェクトにイベントがあることを確認:
// 1. Spline でオブジェクトを選択
// 2. "Events" パネルでイベントを追加
// 3. ステート遷移またはアクションを割り当て
落とし穴 5: プログラム的にアニメーションがトリガーされない
問題: emitEvent() がアニメーションをトリガーしない
解決策:
// ❌ 誤り: シーンロード前に呼び出し
function triggerAnimation() {
splineApp.current.emitEvent('mouseHover', 'Button'); // ロードされていない場合はエラー
}
// ✅ 正解: シーンがロードされていることを確認
const [isLoaded, setIsLoaded] = useState(false);
function onLoad(app) {
splineApp.current = app;
setIsLoaded(true);
}
function triggerAnimation() {
if (isLoaded && splineApp.current) {
splineApp.current.emitEvent('mouseHover', 'Button');
}
}
// また Spline エディターで確認:
// - オブジェクトが正しい名前を持っている ('Button')
// - mouseHover イベントが設定されている
// - イベントにアクション (ステート遷移など) がある
落とし穴 6: Next.js のハイドレーション エラー
問題: サーバーとクライアント レンダリング間のミスマッチ
解決策:
// ❌ 誤り: Next.js で標準インポートを使用
import Spline from '@splinetool/react-spline';
// ✅ 正解: Next.js 固有のインポートを使用
import Spline from '@splinetool/react-spline/next';
// または dynamic インポート を ssr: false で使用
import dynamic from 'next/dynamic';
const Spline = dynamic(
() => import('@splinetool/react-spline'),
{ ssr: false }
);
リソース
公式ドキュメント
- Spline ドキュメント: https://docs.spline.design
- React Spline GitHub: https://github.com/splinetool/react-spline
- Spline コミュニティ: https://spline.community
Spline エディター
- Web アプリ: https://app.spline.design
- デスクトップ アプリ: macOS、Windows、Linux で利用可能
学習リソース
- チュートリアル: https://spline.design/tutorials
- YouTube チャンネル: 公式 Spline チュートリアル
- 例ギャラリー: https://spline.design/community
エクスポート フォーマット
- React コンポーネント (
@splinetool/react-spline経由) - バニラ JavaScript (Web Code API)
- GLTF/GLB (Three.js、Babylon.js 向け)
- USDZ (Apple AR 向け)
- STL (3D プリンティング向け)
- ビデオ/GIF (マーケティング向け)
関連スキル
- threejs-webgl: より制御できるコードファーストの 3D 開発
- react-three-fiber: React と JSX で 3D シーンを構築
- babylonjs-engine: エディター ワークフロー付きの代替 3D エンジン
- motion-framer: Spline コンテナと UI 要素のアニメーション
- gsap-scrolltrigger: スクロール駆動の Spline アニメーション
- figma-dev-mode: デザイン構文のワークフロー (同様のビジュアル アプローチ)
スクリプト
このスキルはユーティリティ スクリプトを含みます:
project_generator.py- Spline + React スターター プロジェクトを生成component_builder.py- イベント付き Spline コンポーネント ラッパーを構築
スキル ディレクトリからスクリプトを実行:
./scripts/project_generator.py
./scripts/component_builder.py
アセット
スターター テンプレートとサンプル:
starter_spline/- 完全な React + Spline テンプレートexamples/- 実世界の統合パターン
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- freshtechbro
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/freshtechbro/claudedesignskills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。