‹ 首页

react-three-fiber

@dedekpo · 收录于 昨天 · 上游提交 1 个月前

Build 3D applications with React Three Fiber (R3F), the React renderer for Three.js. Use this skill when building 3D scenes with React, using declarative JSX for 3D objects, integrating Three.js with React state/lifecycle, or using Drei helpers. Covers Canvas setup, hooks, Drei utilities, performance patterns, and state management for 3D React apps.

适合你,如果正在用 React 开发需要 3D 效果的应用

/ 通过 npx 安装 校验哈希
npx oh-my-skill add dedekpo/stylized-scene/react-three-fiber
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- dedekpo/stylized-scene/react-three-fiber
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify dedekpo/stylized-scene/react-three-fiber
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
88GitHub stars
~2K最小装载
~8.7K含声明引用
~8.7K文本包总量
索引托管

怎么用

商店整理自技能原文 · 版本 531c572 · 表述以原文为准
它做什么

Claude 会根据你的需求,提供 React Three Fiber 代码示例和配置建议,帮你用声明式 JSX 创建 3D 场景、管理状态及优化性能。

什么时候触发

当你提出开发 React 3D 应用、搭建 3D 场景或集成 Three.js 与 React 状态时,该技能被触发。

装好后可以这样说
Claude 会给出完整组件代码。
Claude 会提供导入和用法示例。
技能原文 SKILL.md作者撰写 · MIT · 531c572

React Three Fiber

React Three Fiber (R3F) is a React renderer for Three.js. Write declarative, component-based 3D scenes using JSX.

Library Versions (2026) - React Three Fiber: v9.5+ - @react-three/drei: v9.116+ - @react-three/rapier: v2+ - @react-three/postprocessing: v3+ - React: 19+ (concurrent features supported)
Decision Frameworks
When to Use R3F vs Vanilla Three.js
Is your app already React-based?
  → Yes: Use R3F (natural integration)
  → No: Consider vanilla Three.js

Do you need React state management?
  → Yes: Use R3F (seamless state integration)
  → No: Either works

Is the 3D scene the entire app?
  → Yes: Either works (R3F has slight overhead)
  → No, mixed with React UI: Use R3F

Performance-critical with millions of objects?
  → Consider vanilla Three.js for maximum control
  → R3F is fine for 99% of use cases
When to Use Which State Management
Local component state (single mesh color, hover)?
  → useState / useRef

Shared between few components (selected object)?
  → React Context or prop drilling

Global game/app state (score, inventory, settings)?
  → Zustand (recommended for R3F)

Complex state with actions/reducers?
  → Zustand with slices or Redux Toolkit

Need state persistence?
  → Zustand with persist middleware
When to Use Which Drei Component
Need camera controls?
  ├─ Orbit around object → OrbitControls
  ├─ First-person → PointerLockControls
  ├─ Map/top-down → MapControls
  └─ Smooth transitions → CameraControls

Need environment lighting?
  ├─ Quick preset → <Environment preset="sunset" />
  ├─ Custom HDR → <Environment files="/env.hdr" />
  └─ Performance-sensitive → <Environment blur={0.5} />

Need text?
  ├─ 3D text in scene → <Text3D />
  ├─ 2D text billboards → <Text />
  └─ HTML overlay → <Html />

Need loading?
  ├─ GLTF models → useGLTF
  ├─ Textures → useTexture
  ├─ Progress UI → useProgress
  └─ Preloading → <Preload all />
Core Setup
import { Canvas } from '@react-three/fiber'

function App() {
  return (
    <Canvas
      camera={{ position: [0, 0, 5], fov: 75 }}
      gl={{ antialias: true }}
      shadows
    >
      <ambientLight intensity={0.5} />
      <directionalLight position={[10, 10, 5]} castShadow />
      <mesh>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="orange" />
      </mesh>
    </Canvas>
  )
}
Canvas Props
<Canvas
  camera={{ position, fov, near, far }}  // Camera config
  gl={{ antialias, alpha, powerPreference }}  // WebGL context
  shadows  // Enable shadow maps
  dpr={[1, 2]}  // Device pixel ratio range
  frameloop="demand"  // "always" | "demand" | "never"
  style={{ width: '100%', height: '100vh' }}
  onCreated={({ gl, scene, camera }) => {}}  // Access internals
/>
Essential Hooks
useFrame - Animation Loop
import { useFrame } from '@react-three/fiber'
import { useRef } from 'react'

function SpinningBox() {
  const meshRef = useRef()

  useFrame((state, delta) => {
    // state: { clock, camera, scene, gl, pointer, ... }
    meshRef.current.rotation.y += delta
    meshRef.current.position.y = Math.sin(state.clock.elapsedTime)
  })

  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial />
    </mesh>
  )
}
useThree - Access Internals
import { useThree } from '@react-three/fiber'

function CameraLogger() {
  const { camera, gl, scene, size, viewport, pointer } = useThree()
  // viewport: { width, height } in Three.js units
  // size: { width, height } in pixels
  // pointer: normalized mouse position (-1 to 1)
  return null
}
useLoader - Asset Loading
import { useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

function Model() {
  const gltf = useLoader(GLTFLoader, '/model.glb')
  const texture = useLoader(TextureLoader, '/texture.jpg')

  return <primitive object={gltf.scene} />
}
JSX to Three.js Mapping
// Three.js class → camelCase JSX element
// Constructor args → args prop (array)
// Properties → props

// THREE.Mesh
<mesh position={[0, 1, 0]} rotation={[0, Math.PI, 0]} scale={1.5}>
  {/* THREE.BoxGeometry(1, 2, 1) */}
  <boxGeometry args={[1, 2, 1]} />
  {/* THREE.MeshStandardMaterial({ color: 'red' }) */}
  <meshStandardMaterial color="red" roughness={0.5} />
</mesh>

// Nested properties use dash notation
<directionalLight
  position={[5, 5, 5]}
  castShadow
  shadow-mapSize={[2048, 2048]}
  shadow-camera-far={50}
/>

// Attach to parent properties
<mesh>
  <boxGeometry />
  <meshStandardMaterial>
    <texture attach="map" image={img} />
  </meshStandardMaterial>
</mesh>
Drei - Essential Helpers

Drei provides production-ready abstractions. Install: @react-three/drei

import {
  OrbitControls,
  PerspectiveCamera,
  Environment,
  useGLTF,
  useTexture,
  Text,
  Html,
  Float,
  Stage,
  ContactShadows,
  Sky,
  Stars,
} from '@react-three/drei'
Common Drei Components
// Camera controls
<OrbitControls enableDamping dampingFactor={0.05} />

// Environment lighting (HDR)
<Environment preset="sunset" background />
// Presets: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse

// Load GLTF with draco support
const { scene, nodes, materials } = useGLTF('/model.glb')
useGLTF.preload('/model.glb')

// Load textures
const [colorMap, normalMap] = useTexture(['/color.jpg', '/normal.jpg'])

// 3D Text
<Text fontSize={1} color="white" anchorX="center" anchorY="middle">
  Hello World
</Text>

// HTML overlay in 3D space
<Html position={[0, 2, 0]} center transform occlude>
  <div className="label">Click me</div>
</Html>

// Floating animation
<Float speed={2} rotationIntensity={0.5} floatIntensity={1}>
  <mesh>...</mesh>
</Float>

// Quick studio lighting
<Stage environment="city" intensity={0.5}>
  <Model />
</Stage>

// Soft shadows on ground
<ContactShadows position={[0, -0.5, 0]} opacity={0.5} blur={2} />
Event Handling
<mesh
  onClick={(e) => {
    e.stopPropagation()
    console.log('clicked', e.point, e.face)
  }}
  onPointerOver={(e) => setHovered(true)}
  onPointerOut={(e) => setHovered(false)}
  onPointerMove={(e) => console.log(e.point)}
  onPointerDown={(e) => {}}
  onPointerUp={(e) => {}}
  onDoubleClick={(e) => {}}
  onContextMenu={(e) => {}}
>

Event object includes: point, face, faceIndex, distance, object, eventObject, camera, ray.

State Management
With Zustand (Recommended)
import { create } from 'zustand'

const useStore = create((set) => ({
  score: 0,
  gameState: 'idle',
  addScore: (points) => set((state) => ({ score: state.score + points })),
  startGame: () => set({ gameState: 'playing' }),
}))

function ScoreDisplay() {
  const score = useStore((state) => state.score)
  return <Text>{score}</Text>
}

function GameLogic() {
  const addScore = useStore((state) => state.addScore)
  useFrame(() => {
    // Game logic that calls addScore
  })
  return null
}
With React Context
const GameContext = createContext()

function GameProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState)
  return (
    <GameContext.Provider value={{ state, dispatch }}>
      {children}
    </GameContext.Provider>
  )
}

// Wrap Canvas content
<Canvas>
  <GameProvider>
    <Scene />
  </GameProvider>
</Canvas>
Performance Patterns
Instancing
import { Instances, Instance } from '@react-three/drei'

function Boxes({ count = 1000 }) {
  return (
    <Instances limit={count}>
      <boxGeometry />
      <meshStandardMaterial />
      {Array.from({ length: count }, (_, i) => (
        <Instance
          key={i}
          position={[Math.random() * 100, Math.random() * 100, Math.random() * 100]}
          color={`hsl(${Math.random() * 360}, 50%, 50%)`}
        />
      ))}
    </Instances>
  )
}
Selective Rendering
// Only re-render when needed
<Canvas frameloop="demand">
  {/* Call invalidate() to trigger render */}
</Canvas>

function Controls() {
  const { invalidate } = useThree()
  return <OrbitControls onChange={() => invalidate()} />
}
Memoization
// Memoize expensive components
const ExpensiveModel = memo(function ExpensiveModel({ url }) {
  const gltf = useGLTF(url)
  return <primitive object={gltf.scene.clone()} />
})

// Memoize materials/geometries outside components
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({ color: 'red' })

function Box() {
  return (
    <mesh geometry={geometry} material={material} />
  )
}
Adaptive Performance
import { PerformanceMonitor, AdaptiveDpr, AdaptiveEvents } from '@react-three/drei'

<Canvas>
  <PerformanceMonitor
    onDecline={() => setQuality('low')}
    onIncline={() => setQuality('high')}
  >
    <AdaptiveDpr pixelated />
    <AdaptiveEvents />
    <Scene quality={quality} />
  </PerformanceMonitor>
</Canvas>
Related Skills

| When you need... | Use skill | |------------------|-----------| | Vanilla Three.js (no React) | → threejs | | Optimize assets before loading | → asset-pipeline-3d | | Debug visual/performance issues | → graphics-troubleshooting |

Reference Files
  • [references/drei.md](references/drei.md) - Complete Drei component reference
  • [references/physics.md](references/physics.md) - @react-three/rapier integration
  • [references/postprocessing.md](references/postprocessing.md) - @react-three/postprocessing effects
  • [references/state.md](references/state.md) - Zustand patterns for R3F
按 MIT 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。