Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

react-three-fiber

React Three Fiber(R3F)を使用して、Three.jsをReactで扱うための宣言的な3Dシーンを構築します。コンポーネントベースのアーキテクチャや状態管理、再利用可能な抽象化を活かしてReactアプリケーション内でインタラクティブな3D体験を実装する際に使用します。製品コンフィギュレーター、ポートフォリオ、ゲーム、データビジュアライゼーション、没入型Webエクスペリエンスの開発に最適です。

description の原文を見る

Build declarative 3D scenes with React Three Fiber (R3F) - a React renderer for Three.js. Use when building interactive 3D experiences in React applications with component-based architecture, state management, and reusable abstractions. Ideal for product configurators, portfolios, games, data visualization, and immersive web experiences.

SKILL.md 本文

React Three Fiber

概要

React Three Fiber (R3F) は、Three.js 用の React レンダラーで、React アプリケーションに宣言型でコンポーネントベースの 3D 開発をもたらします。Three.js オブジェクトを命令型で作成・管理する代わりに、Three.js オブジェクトに直接マップされる JSX コンポーネントを使用して 3D シーンを構築します。

このスキルを使用する場合:

  • React アプリケーション内で 3D エクスペリエンスを構築する場合
  • インタラクティブな製品コンフィギュレータやショーケースを作成する場合
  • 3D ポートフォリオ、ギャラリー、ストーリーテリング体験を開発する場合
  • React でゲームやシミュレーションを構築する場合
  • 既存の React プロジェクトに 3D 要素を追加する場合
  • 状態管理と React フックを 3D グラフィックスで使用する必要がある場合
  • React フレームワーク (Next.js, Gatsby, Remix) で作業する場合

主な利点:

  • 宣言型: React コンポーネントのような 3D シーンを記述
  • React 統合: フック、コンテキスト、状態管理への完全なアクセス
  • 再利用性: 3D コンポーネントライブラリの作成と共有
  • パフォーマンス: 自動レンダー最適化と調整
  • エコシステム: Drei ヘルパー、Zustand、Framer Motion などと連携
  • TypeScript サポート: Three.js オブジェクトの完全な型安全性

コアコンセプト

1. Canvas コンポーネント

<Canvas> コンポーネントは、Three.js シーン、カメラ、レンダラー、レンダリングループを設定します。

import { Canvas } from '@react-three/fiber'

function App() {
  return (
    <Canvas
      camera={{ position: [0, 0, 5], fov: 75 }}
      gl={{ antialias: true }}
      dpr={[1, 2]}
    >
      {/* 3D コンテンツはここに配置 */}
    </Canvas>
  )
}

Canvas Props:

  • camera - カメラ設定 (position, fov, near, far)
  • gl - WebGL レンダラー設定
  • dpr - デバイスピクセル比 (デフォルト: [1, 2])
  • shadows - シャドウマッピングを有効化 (デフォルト: false)
  • frameloop - "always" (デフォルト)、"demand"、または "never"
  • flat - シンプルな色のための色管理を無効化
  • linear - sRGB の代わりに線形色空間を使用

2. 宣言型 3D オブジェクト

Three.js オブジェクトは JSX とケバブケース props を使用して作成されます:

// THREE.Mesh + THREE.BoxGeometry + THREE.MeshStandardMaterial
<mesh position={[0, 0, 0]} rotation={[0, Math.PI / 4, 0]}>
  <boxGeometry args={[1, 1, 1]} />
  <meshStandardMaterial color="hotpink" />
</mesh>

Prop マッピング:

  • positionobject.position.set(x, y, z)
  • rotationobject.rotation.set(x, y, z)
  • scaleobject.scale.set(x, y, z)
  • args → ジオメトリ/マテリアルのコンストラクタ引数
  • attach → 親プロパティにアタッチ (例: attach="material")

短縮記法:

// フル記法
<mesh position={[1, 2, 3]} />

// 軸ごと (ダッシュ記法)
<mesh position-x={1} position-y={2} position-z={3} />

3. useFrame フック

フレーム (アニメーションループ) ごとにコードを実行:

import { useFrame } from '@react-three/fiber'
import { useRef } from 'react'

function RotatingBox() {
  const meshRef = useRef()

  useFrame((state, delta) => {
    // フレームごとにメッシュを回転
    meshRef.current.rotation.x += delta
    meshRef.current.rotation.y += delta * 0.5

    // シーン状態にアクセス
    const time = state.clock.elapsedTime
    meshRef.current.position.y = Math.sin(time) * 2
  })

  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="orange" />
    </mesh>
  )
}

useFrame パラメータ:

  • state - シーン状態 (camera, scene, gl, clock など)
  • delta - 最後のフレーム以降の経過時間 (フレームレート独立性のため)
  • xrFrame - XR フレームデータ (VR/AR 用)

重要: useFrame 内で setState を使用しないこと - 不要な再レンダーを引き起こします!

4. useThree フック

シーン状態とメソッドにアクセス:

import { useThree } from '@react-three/fiber'

function CameraInfo() {
  const { camera, gl, scene, size, viewport } = useThree()

  // 選択的購読 (サイズ変更時のみ再レンダー)
  const size = useThree((state) => state.size)

  // 状態を非反応的に取得
  const get = useThree((state) => state.get)
  const freshState = get() // 再レンダーをトリガーしない最新状態

  return null
}

利用可能な状態:

  • camera - デフォルトカメラ
  • scene - Three.js シーン
  • gl - WebGL レンダラー
  • size - キャンバス寸法
  • viewport - 3D 単位のビューポート寸法
  • clock - Three.js クロック
  • pointer - 正規化されたマウス座標
  • invalidate() - 手動でレンダーをトリガー
  • setSize() - 手動でキャンバスをリサイズ

5. useLoader フック

自動キャッシュと Suspense 統合でアセットを読み込む:

import { Suspense } from 'react'
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { TextureLoader } from 'three'

function Model() {
  const gltf = useLoader(GLTFLoader, '/model.glb')
  return <primitive object={gltf.scene} />
}

function TexturedMesh() {
  const texture = useLoader(TextureLoader, '/texture.jpg')
  return (
    <mesh>
      <boxGeometry />
      <meshStandardMaterial map={texture} />
    </mesh>
  )
}

function App() {
  return (
    <Canvas>
      <Suspense fallback={<LoadingIndicator />}>
        <Model />
        <TexturedMesh />
      </Suspense>
    </Canvas>
  )
}

複数アセットの読み込み:

const [texture1, texture2, texture3] = useLoader(TextureLoader, [
  '/tex1.jpg',
  '/tex2.jpg',
  '/tex3.jpg'
])

ローダー拡張:

import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'

useLoader(GLTFLoader, '/model.glb', (loader) => {
  const dracoLoader = new DRACOLoader()
  dracoLoader.setDecoderPath('/draco/')
  loader.setDRACOLoader(dracoLoader)
})

事前読み込み:

// コンポーネントがマウントされる前にアセットを事前読み込み
useLoader.preload(GLTFLoader, '/model.glb')

一般的なパターン

パターン 1: 基本的なシーン設定

import { Canvas } from '@react-three/fiber'

function Scene() {
  return (
    <>
      {/* ライト */}
      <ambientLight intensity={0.5} />
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />

      {/* オブジェクト */}
      <mesh position={[0, 0, 0]}>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    </>
  )
}

function App() {
  return (
    <Canvas camera={{ position: [0, 0, 5], fov: 75 }}>
      <Scene />
    </Canvas>
  )
}

パターン 2: インタラクティブオブジェクト (クリック、ホバー)

import { useState } from 'react'

function InteractiveBox() {
  const [hovered, setHovered] = useState(false)
  const [active, setActive] = useState(false)

  return (
    <mesh
      scale={active ? 1.5 : 1}
      onClick={() => setActive(!active)}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <boxGeometry />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

パターン 3: useFrame でのアニメーションコンポーネント

import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'

function AnimatedSphere() {
  const meshRef = useRef()

  useFrame((state, delta) => {
    // 回転
    meshRef.current.rotation.y += delta

    // 位置を振動
    const time = state.clock.elapsedTime
    meshRef.current.position.y = Math.sin(time) * 2
  })

  return (
    <mesh ref={meshRef}>
      <sphereGeometry args={[1, 32, 32]} />
      <meshStandardMaterial color="cyan" />
    </mesh>
  )
}

パターン 4: GLTF モデルの読み込み

import { Suspense } from 'react'
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

function Model({ url }) {
  const gltf = useLoader(GLTFLoader, url)

  return (
    <primitive
      object={gltf.scene}
      scale={0.5}
      position={[0, 0, 0]}
    />
  )
}

function App() {
  return (
    <Canvas>
      <Suspense fallback={<LoadingPlaceholder />}>
        <Model url="/model.glb" />
      </Suspense>
    </Canvas>
  )
}

function LoadingPlaceholder() {
  return (
    <mesh>
      <boxGeometry />
      <meshBasicMaterial wireframe />
    </mesh>
  )
}

パターン 5: 複数のライト

function Lighting() {
  return (
    <>
      {/* ベース照度用の環境光 */}
      <ambientLight intensity={0.3} />

      {/* シャドウ付き平行光 */}
      <directionalLight
        position={[5, 5, 5]}
        intensity={1}
        castShadow
        shadow-mapSize-width={2048}
        shadow-mapSize-height={2048}
      />

      {/* アクセント用ポイントライト */}
      <pointLight position={[-5, 5, -5]} intensity={0.5} color="blue" />

      {/* フォーカスした照度用スポットライト */}
      <spotLight
        position={[10, 10, 10]}
        angle={0.3}
        penumbra={1}
        intensity={1}
      />
    </>
  )
}

パターン 6: インスタンシング (多数オブジェクト)

import { useMemo, useRef } from 'react'
import * as THREE from 'three'
import { useFrame } from '@react-three/fiber'

function Particles({ count = 1000 }) {
  const meshRef = useRef()

  // ランダムな位置を生成
  const particles = useMemo(() => {
    const temp = []
    for (let i = 0; i < count; i++) {
      const t = Math.random() * 100
      const factor = 20 + Math.random() * 100
      const speed = 0.01 + Math.random() / 200
      const x = Math.random() * 2 - 1
      const y = Math.random() * 2 - 1
      const z = Math.random() * 2 - 1
      temp.push({ t, factor, speed, x, y, z, mx: 0, my: 0 })
    }
    return temp
  }, [count])

  const dummy = useMemo(() => new THREE.Object3D(), [])

  useFrame(() => {
    particles.forEach((particle, i) => {
      let { t, factor, speed, x, y, z } = particle
      t = particle.t += speed / 2
      const a = Math.cos(t) + Math.sin(t * 1) / 10
      const b = Math.sin(t) + Math.cos(t * 2) / 10
      const s = Math.cos(t)

      dummy.position.set(
        x + Math.cos((t / 10) * factor) + (Math.sin(t * 1) * factor) / 10,
        y + Math.sin((t / 10) * factor) + (Math.cos(t * 2) * factor) / 10,
        z + Math.cos((t / 10) * factor) + (Math.sin(t * 3) * factor) / 10
      )
      dummy.scale.set(s, s, s)
      dummy.updateMatrix()
      meshRef.current.setMatrixAt(i, dummy.matrix)
    })
    meshRef.current.instanceMatrix.needsUpdate = true
  })

  return (
    <instancedMesh ref={meshRef} args={[null, null, count]}>
      <sphereGeometry args={[0.05, 8, 8]} />
      <meshBasicMaterial color="white" />
    </instancedMesh>
  )
}

パターン 7: グループとネスティング

function Robot() {
  return (
    <group position={[0, 0, 0]}>
      {/* 胴体 */}
      <mesh position={[0, 0, 0]}>
        <boxGeometry args={[1, 2, 1]} />
        <meshStandardMaterial color="gray" />
      </mesh>

      {/* 頭 */}
      <mesh position={[0, 1.5, 0]}>
        <sphereGeometry args={[0.5, 32, 32]} />
        <meshStandardMaterial color="silver" />
      </mesh>

      {/* 腕 */}
      <group position={[-0.75, 0.5, 0]}>
        <mesh>
          <cylinderGeometry args={[0.1, 0.1, 1.5]} />
          <meshStandardMaterial color="darkgray" />
        </mesh>
      </group>

      <group position={[0.75, 0.5, 0]}>
        <mesh>
          <cylinderGeometry args={[0.1, 0.1, 1.5]} />
          <meshStandardMaterial color="darkgray" />
        </mesh>
      </group>
    </group>
  )
}

Drei ヘルパーとの統合

Drei は R3F の必須ヘルパーライブラリで、すぐに使用可能なコンポーネントを提供します:

OrbitControls

import { OrbitControls } from '@react-three/drei'

<Canvas>
  <OrbitControls
    makeDefault
    enableDamping
    dampingFactor={0.05}
    minDistance={3}
    maxDistance={20}
  />
  <Box />
</Canvas>

Environment & Lighting

import { Environment, ContactShadows } from '@react-three/drei'

<Canvas>
  {/* HDRI 環境マップ */}
  <Environment preset="sunset" />

  {/* またはカスタム */}
  <Environment files="/hdri.hdr" />

  {/* ソフトコンタクトシャドウ */}
  <ContactShadows
    opacity={0.5}
    scale={10}
    blur={1}
    far={10}
    resolution={256}
  />

  <Model />
</Canvas>

Text

import { Text, Text3D } from '@react-three/drei'

// 2D ビルボードテキスト
<Text
  position={[0, 2, 0]}
  fontSize={1}
  color="white"
  anchorX="center"
  anchorY="middle"
>
  Hello World
</Text>

// 3D 押し出しテキスト
<Text3D
  font="/fonts/helvetiker_regular.typeface.json"
  size={1}
  height={0.2}
>
  3D Text
  <meshNormalMaterial />
</Text3D>

useGLTF フック (Drei)

import { useGLTF } from '@react-three/drei'

function Model() {
  const { scene, materials, nodes } = useGLTF('/model.glb')

  return <primitive object={scene} />
}

// 事前読み込み
useGLTF.preload('/model.glb')

Center & Bounds

import { Center, Bounds, useBounds } from '@react-three/drei'

// オブジェクトを自動中央配置
<Center>
  <Model />
</Center>

// カメラを範囲に自動フィット
<Bounds fit clip observe margin={1.2}>
  <Model />
</Bounds>

HTML オーバーレイ

import { Html } from '@react-three/drei'

<mesh>
  <boxGeometry />
  <meshStandardMaterial />

  <Html
    position={[0, 1, 0]}
    center
    distanceFactor={10}
  >
    <div className="annotation">
      これはボックスです
    </div>
  </Html>
</mesh>

スクロールコントロール

import { ScrollControls, Scroll, useScroll } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'

function AnimatedScene() {
  const scroll = useScroll()
  const meshRef = useRef()

  useFrame(() => {
    const offset = scroll.offset // 0-1 正規化スクロール位置
    meshRef.current.position.y = offset * 10
  })

  return <mesh ref={meshRef}>...</mesh>
}

<Canvas>
  <ScrollControls pages={3} damping={0.5}>
    <Scroll>
      <AnimatedScene />
    </Scroll>

    {/* HTML オーバーレイ */}
    <Scroll html>
      <div style={{ height: '100vh' }}>
        <h1>スクロール可能なコンテンツ</h1>
      </div>
    </Scroll>
  </ScrollControls>
</Canvas>

その他のライブラリとの統合

GSAP との統合

import { useRef, useEffect } from 'react'
import { useFrame } from '@react-three/fiber'
import gsap from 'gsap'

function AnimatedBox() {
  const meshRef = useRef()

  useEffect(() => {
    // GSAP タイムラインアニメーション
    const tl = gsap.timeline({ repeat: -1, yoyo: true })

    tl.to(meshRef.current.position, {
      y: 2,
      duration: 1,
      ease: 'power2.inOut'
    })
    .to(meshRef.current.rotation, {
      y: Math.PI * 2,
      duration: 2,
      ease: 'none'
    }, 0)

    return () => tl.kill()
  }, [])

  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="orange" />
    </mesh>
  )
}

Framer Motion との統合

import { motion } from 'framer-motion-3d'

function AnimatedSphere() {
  return (
    <motion.mesh
      initial={{ scale: 0 }}
      animate={{ scale: 1 }}
      transition={{ duration: 1 }}
    >
      <sphereGeometry />
      <meshStandardMaterial color="hotpink" />
    </motion.mesh>
  )
}

Zustand との統合 (状態管理)

import create from 'zustand'

const useStore = create((set) => ({
  color: 'orange',
  setColor: (color) => set({ color })
}))

function Box() {
  const color = useStore((state) => state.color)
  const setColor = useStore((state) => state.setColor)

  return (
    <mesh onClick={() => setColor('hotpink')}>
      <boxGeometry />
      <meshStandardMaterial color={color} />
    </mesh>
  )
}

パフォーマンス最適化

1. オンデマンドレンダリング

<Canvas frameloop="demand">
  {/* 必要な場合のみレンダリング */}
</Canvas>

// 手動でレンダーをトリガー
function MyComponent() {
  const invalidate = useThree((state) => state.invalidate)

  return (
    <mesh onClick={() => invalidate()}>
      <boxGeometry />
      <meshStandardMaterial />
    </mesh>
  )
}

2. インスタンシング

多くの同一オブジェクトをレンダリングするには <instancedMesh> を使用:

function Particles({ count = 10000 }) {
  const meshRef = useRef()

  useEffect(() => {
    const temp = new THREE.Object3D()

    for (let i = 0; i < count; i++) {
      temp.position.set(
        Math.random() * 10 - 5,
        Math.random() * 10 - 5,
        Math.random() * 10 - 5
      )
      temp.updateMatrix()
      meshRef.current.setMatrixAt(i, temp.matrix)
    }

    meshRef.current.instanceMatrix.needsUpdate = true
  }, [count])

  return (
    <instancedMesh ref={meshRef} args={[null, null, count]}>
      <sphereGeometry args={[0.1, 8, 8]} />
      <meshBasicMaterial color="white" />
    </instancedMesh>
  )
}

3. フラスタムカリング

カメラビューの外側のオブジェクトは自動的にカリングされます。

// 常に表示されるオブジェクトに対して無効化
<mesh frustumCulled={false}>
  <boxGeometry />
  <meshStandardMaterial />
</mesh>

4. LOD (レベルオブディテール)

import { Detailed } from '@react-three/drei'

<Detailed distances={[0, 10, 20]}>
  {/* 高詳細 - カメラに近い */}
  <mesh geometry={highPolyGeometry} />

  {/* 中詳細 */}
  <mesh geometry={mediumPolyGeometry} />

  {/* 低詳細 - カメラから遠い */}
  <mesh geometry={lowPolyGeometry} />
</Detailed>

5. 適応型パフォーマンス

import { AdaptiveDpr, AdaptiveEvents, PerformanceMonitor } from '@react-three/drei'

<Canvas>
  {/* パフォーマンス低下時に DPR を削減 */}
  <AdaptiveDpr pixelated />

  {/* レイキャスト頻度を削減 */}
  <AdaptiveEvents />

  {/* パフォーマンスを監視して対応 */}
  <PerformanceMonitor
    onIncline={() => console.log('パフォーマンス向上')}
    onDecline={() => console.log('パフォーマンス低下')}
  >
    <Scene />
  </PerformanceMonitor>
</Canvas>

6. 選択的再レンダー

useThree セレクタを使用して不要な再レンダーを回避:

// ❌ 任意の状態変更で再レンダー
const state = useThree()

// ✅ サイズ変更時のみ再レンダー
const size = useThree((state) => state.size)

// ✅ カメラ変更時のみ再レンダー
const camera = useThree((state) => state.camera)

一般的な落とし穴と解決策

❌ 落とし穴 1: useFrame 内の setState

// ❌ 悪い例: フレーム毎に React 再レンダーをトリガー
const [x, setX] = useState(0)
useFrame(() => setX((x) => x + 0.1))
return <mesh position-x={x} />

解決策: ref を直接変更

// ✅ 良い例: 直接変更、再レンダーなし
const meshRef = useRef()
useFrame((state, delta) => {
  meshRef.current.position.x += delta
})
return <mesh ref={meshRef} />

❌ 落とし穴 2: レンダー内でのオブジェクト作成

// ❌ 悪い例: フレーム毎に新しい Vector3 を作成
<mesh position={new THREE.Vector3(1, 2, 3)} />

解決策: 配列記法または useMemo を使用

// ✅ 良い例: 配列記法を使用
<mesh position={[1, 2, 3]} />

// または複雑なオブジェクトに useMemo を使用
const position = useMemo(() => new THREE.Vector3(1, 2, 3), [])
<mesh position={position} />

❌ 落とし穴 3: useLoader キャッシュを使用しない

// ❌ 悪い例: レンダー毎にテクスチャを読み込む
function Component() {
  const [texture, setTexture] = useState()
  useEffect(() => {
    new TextureLoader().load('/texture.jpg', setTexture)
  }, [])
  return texture ? <meshBasicMaterial map={texture} /> : null
}

解決策: useLoader を使用 (自動キャッシング)

// ✅ 良い例: キャッシュされて再利用
function Component() {
  const texture = useLoader(TextureLoader, '/texture.jpg')
  return <meshBasicMaterial map={texture} />
}

❌ 落とし穴 4: 条件付きマウント (高コスト)

// ❌ 悪い例: アンマウントとリマウント (高コスト)
{stage === 1 && <Stage1 />}
{stage === 2 && <Stage2 />}
{stage === 3 && <Stage3 />}

解決策: visible prop を使用

// ✅ 良い例: コンポーネントはマウントされたまま、非表示
<Stage1 visible={stage === 1} />
<Stage2 visible={stage === 2} />
<Stage3 visible={stage === 3} />

function Stage1({ visible, ...props }) {
  return <group {...props} visible={visible}>...</group>
}

❌ 落とし穴 5: Canvas 外で useThree を使用

// ❌ 悪い例: クラッシュ - useThree は Canvas 内である必要があります
function App() {
  const { size } = useThree()
  return <Canvas>...</Canvas>
}

解決策: Canvas の子内でフックを使用

// ✅ 良い例: Canvas 子内で useThree を使用
function CameraInfo() {
  const { size } = useThree()
  return null
}

function App() {
  return (
    <Canvas>
      <CameraInfo />
    </Canvas>
  )
}

❌ 落とし穴 6: リソースの破棄忘れ

// ❌ 悪い例: メモリリーク - テクスチャが破棄されていない
const texture = useLoader(TextureLoader, '/texture.jpg')

解決策: R3F は自動的に破棄を処理しますが、手動での Three.js オブジェクトに注意

// ✅ 良い例: 必要に応じて手動でクリーンアップ
useEffect(() => {
  const geometry = new THREE.SphereGeometry(1)
  const material = new THREE.MeshBasicMaterial()

  return () => {
    geometry.dispose()
    material.dispose()
  }
}, [])

ベストプラクティス

1. コンポーネント構成

シーンを再利用可能なコンポーネントに分割:

function Lights() {
  return (
    <>
      <ambientLight intensity={0.5} />
      <spotLight position={[10, 10, 10]} angle={0.15} />
    </>
  )
}

function Scene() {
  return (
    <>
      <Lights />
      <Model />
      <Ground />
      <Effects />
    </>
  )
}

<Canvas>
  <Scene />
</Canvas>

2. 重いアセットを Suspend

常に非同期操作を Suspense でラップ:

<Canvas>
  <Suspense fallback={<Loader />}>
    <Model />
    <Environment />
  </Suspense>
</Canvas>

3. TypeScript を使用

import { ThreeElements } from '@react-three/fiber'

function Box(props: ThreeElements['mesh']) {
  return (
    <mesh {...props}>
      <boxGeometry />
      <meshStandardMaterial />
    </mesh>
  )
}

4. 機能ごとに整理

src/
  components/
    3d/
      Scene.tsx
      Lights.tsx
      Camera.tsx
    models/
      Robot.tsx
      Character.tsx
    effects/
      PostProcessing.tsx

5. React DevTools Profiler でテスト

再レンダーを監視し、パフォーマンスの問題を引き起こしているコンポーネントを最適化します。


リソース

参考資料

  • references/api_reference.md - R3F & Drei 完全 API ドキュメント
  • references/hooks_guide.md - 詳細なフック使用法とパターン
  • references/drei_helpers.md - 包括的な Drei ライブラリガイド

スクリプト

  • scripts/component_generator.py - R3F コンポーネントボイラープレートを生成
  • scripts/scene_setup.py - 一般的なパターンで R3F シーンを初期化

アセット

  • assets/starter_r3f/ - 完全な R3F + Vite スターターテンプレート
  • assets/examples/ - 実世界の R3F コンポーネント例

外部リソース

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
freshtechbro
リポジトリ
freshtechbro/claudedesignskills
ライセンス
MIT
最終更新
不明

Source: https://github.com/freshtechbro/claudedesignskills / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: freshtechbro · freshtechbro/claudedesignskills · ライセンス: MIT