spline-interactive について
Spline でインタラクティブな 3D 表現を作るクリエイターや開発者向けのスキルです。ビジュアルモデリング、状態アニメーション、イベント、シーンの書き出し、React 連携、モバイル最適化を解説します。
主な機能
- 01ビジュアルな 3D モデリングとシーン構成
- 02状態アニメーションとイベント操作
- 03React、ウェブコード、モデルの書き出し
- 04React へのシーン埋め込みとオブジェクト制御
- 05読み込みとモバイル性能の最適化
活用シーン
- 01インタラクティブな製品紹介を作成
- 02マーケティングページに 3D シーンを埋め込む
- 03製品コンフィギュレーターを試作
- 04シーンを React プロジェクトに書き出す
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill spline-interactiveインストール後、Claude Code で/spline-interactiveを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/README.mdreferences/api_reference.mdscripts/component_builder.pyproject_generator.py詳細
Spline インタラクティブ - ブラウザベースの3Dデザインとアニメーション
概要
Splineは、コードや専門的なソフトウェアの知識がなくても、クリエイターがインタラクティブな3D体験を構築できる、ブラウザベースの3Dデザイン・アニメーションプラットフォームです。複数のプラットフォーム向けに3Dシーンをデザイン、アニメーション化、エクスポートできる、共同作業に対応したビジュアルエディターを提供します。
主な機能:
- パラメトリックシェイプ、押し出し、ブール演算を使ったビジュアル3Dモデリング
- タイムライン制御に対応したステートベースのアニメーションシステム
- インタラクティブなイベントシステム(マウス、キーボード、衝突、スクロール)
- 複数のエクスポート方法(Reactコンポーネント、Webコード、公開URL)
- チームライブラリを使ったリアルタイムの共同作業
- AIを活用した生成(テキストからの3D生成、テクスチャ、スタイル転送)
- 組み込みの物理演算とパーティクルシステム
このスキルを使用する場面:
- Three.jsコードを書かずに3Dウェブ体験を作成する
- インタラクティブな製品紹介やコンフィギュレーターをデザインする
- 3D UI/UXのコンセプトをビジュアルにプロトタイプ化する
- 3D要素を使ったマーケティングページを構築する
- デザイナーと協力して3Dコンテンツを制作する
- ReactやVanilla 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コンポーネントまたはVanilla JS
- Spline Viewer:埋め込みiframe
- セルフホスト:ダウンロードして独自にホスト
一般的なパターン
パターン1:基本的なReact統合
用途:SplineシーンをReactアプリケーションに埋め込む
実装:
# Installation
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) {
// Check if clicked object is the button
if (e.target.name === 'Button') {
console.log('Button clicked!');
// Get object properties
console.log('Position:', e.target.position);
console.log('Rotation:', e.target.rotation);
console.log('Scale:', e.target.scale);
}
}
function onSplineMouseHover(e) {
if (e.target.name === 'Button') {
console.log('Hovering over button');
}
}
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) {
// Save Spline instance
splineApp.current = spline;
// Find object by name
const obj = spline.findObjectByName('Product');
// Or by ID
// const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E');
cube.current = obj;
}
function rotateProduct() {
if (cube.current) {
// Rotate 45 degrees around Y axis
cube.current.rotation.y += Math.PI / 4;
}
}
function changeColor() {
if (cube.current) {
// Change material color (hex color)
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}>Rotate</button>
<button onClick={changeColor}>Change Color</button>
<button onClick={moveProduct}>Move</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() {
// Emit mouseHover event on 'Card' object
splineApp.current.emitEvent('mouseHover', 'Card');
}
function triggerClickAnimation() {
// Emit mouseDown event on 'Button' object
splineApp.current.emitEvent('mouseDown', 'Button');
}
function reverseAnimation() {
// Play animation in reverse
splineApp.current.emitEventReverse('mouseHover', 'Card');
}
return (
<div>
<Spline
scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode"
onLoad={onLoad}
/>
<button onClick={triggerHoverAnimation}>Hover Effect</button>
<button onClick={triggerClickAnimation}>Click Effect</button>
<button onClick={reverseAnimation}>Reverse</button>
</div>
);
}
利用可能なイベントタイプ:
mouseDown- マウスの押下mouseHover- ホバー効果mouseUp- マウスのリリースkeyDown- キーの押下keyUp- キーのリリースstart- 開始イベントlookAt- カメラを見るfollow- カメラを追従する
パターン 5:SSR による Next.js との統合
ユースケース:サーバーサイドレンダリングのメリットを活かして、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';
// Dynamically import Spline
const Spline = React.lazy(() => import('@splinetool/react-spline'));
export default function LazyScene() {
return (
<div>
<h1>My Page Content</h1>
<Suspense fallback={<div>Loading 3D scene...</div>}>
<div style={{ width: '100%', height: '500px' }}>
<Spline scene="https://prod.spline.design/YOUR-SCENE-ID/scene.splinecode" />
</div>
</Suspense>
<p>More content below</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) {
// Zoom out on mobile
splineApp.current.setZoom(0.7);
// Adjust camera position
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);
// Add custom behaviors
});
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} // Default is true
/>
2. Spline エディターでシーンを最適化する
Spline での設定:
- ポリゴン数を減らします(デシメーションを使用)
- テクスチャを圧縮します(解像度を下げ、PNG より JPG を使用)
- ライトの数を制限します(最大 2~3 個)
- 可能な場合はシンプルなマテリアルを使用します
- 遠くのオブジェクトに LOD(詳細度)を有効にします
3. サイズの大きいシーンを遅延読み込みする
パターン 6 に示すように React.lazy() を使用します
4. 重要なシーンを事前読み込みする
import { useEffect } from 'react';
import Spline from '@splinetool/react-spline';
export default function PreloadedScene() {
useEffect(() => {
// Preload scene assets
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 コンポーネントはレンダリングされますが、シーンが表示されません
解決策:
// ❌ Wrong: Invalid scene URL
<Spline scene="my-scene.splinecode" />
// ✅ Correct: Full URL from Spline export
<Spline scene="https://prod.spline.design/KFonZGtsoUXP-qx7/scene.splinecode" />
// Check for errors
function onLoad(app) {
console.log('Scene loaded successfully', app);
}
<Spline scene={sceneUrl} onLoad={onLoad} />
次の点も確認してください:
- Spline エディターでシーンが公開されている
- ネットワークタブにファイルのダウンロード成功が表示されている
- コンソールに CORS エラーがない
問題 2:再レンダリング後にオブジェクト参照が失われる
問題:コンポーネントの更新後、オブジェクトの参照が undefined になります
解決策:
// ❌ Wrong: Storing objects without proper refs
let myObject;
function onLoad(spline) {
myObject = spline.findObjectByName('Cube'); // Lost on re-render
}
// ✅ Correct: Use React refs
const myObject = useRef();
function onLoad(spline) {
myObject.current = spline.findObjectByName('Cube');
}
問題 3:モバイルでパフォーマンスの問題が発生する
問題:モバイルデバイスでシーンの動作が遅くなります
解決策:
// Create mobile-optimized version in Spline editor
// - Fewer polygons (< 50k triangles)
// - Smaller textures (512x512 or less)
// - No shadows or reflections
// - Simpler materials
// Load appropriate version
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:イベントが発生しない
問題:クリックイベントやホバーイベントがトリガーされません
解決策:
// ❌ Wrong: Using wrong event name
<Spline onMouseDown={handler} /> // Not a Spline prop
// ✅ Correct: Use Spline event props
<Spline onSplineMouseDown={handler} />
// Also ensure object has events in Spline editor:
// 1. Select object in Spline
// 2. Add event in "Events" panel
// 3. Assign state transition or action
問題 5:プログラムからアニメーションをトリガーできない
問題:emitEvent() でアニメーションがトリガーされません
解決策:
// ❌ Wrong: Calling before scene loads
function triggerAnimation() {
splineApp.current.emitEvent('mouseHover', 'Button'); // Error if not loaded
}
// ✅ Correct: Ensure scene is loaded
const [isLoaded, setIsLoaded] = useState(false);
function onLoad(app) {
splineApp.current = app;
setIsLoaded(true);
}
function triggerAnimation() {
if (isLoaded && splineApp.current) {
splineApp.current.emitEvent('mouseHover', 'Button');
}
}
// Also verify in Spline editor:
// - Object has the correct name ('Button')
// - mouseHover event is configured
// - Event has action (state transition, etc.)
問題 6:Next.js でハイドレーションエラーが発生する
問題:サーバー側のレンダリングとクライアント側のレンダリングに不一致があります
解決策:
// ❌ Wrong: Using standard import in Next.js
import Spline from '@splinetool/react-spline';
// ✅ Correct: Use Next.js-specific import
import Spline from '@splinetool/react-spline/next';
// Or use dynamic import with 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 エディター
- ウェブアプリ:https://app.spline.design
- デスクトップアプリ:macOS、Windows、Linux で利用可能
学習リソース
- チュートリアル:https://spline.design/tutorials
- YouTube チャンネル:Spline 公式チュートリアル
- サンプルギャラリー:https://spline.design/community
エクスポート形式
- React コンポーネント(
@splinetool/react-spline経由) - Vanilla 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/- 実際の統合パターン