Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计提醒

r3f-loadersr3f 装载机

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

9,549

周安装

406

GitHub Stars

79

下载量

3,345
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:r3f-loaders(r3f 装载机)
来源仓库:https://github.com/enzed/r3f-skills
仓库路径:skills/r3f-loaders
安装命令:
npx skills add https://github.com/enzed/r3f-skills --skill r3f-loaders
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/enzed/r3f-skills --skill r3f-loaders

简介

r3f-loaders 用于辅助前端页面、组件和交互逻辑的开发与维护,适合生成或审查 React 相关代码。

  • 适用于前端设计类任务,可帮助整理组件结构或定位布局问题。
  • 使用时需结合项目现有设计系统和构建方式,避免生成孤立片段。
  • 涉及页面改动时应配合本地预览和构建检查确认视觉效果。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

React Three Fiber Loaders

Quick Start

import { Canvas } from '@react-three/fiber'
import { useGLTF, OrbitControls } from '@react-three/drei'
import { Suspense } from 'react'

function Model() {
  const { scene } = useGLTF('/models/robot.glb')
  return <primitive object={scene} />
}

export default function App() {
  return (
    <Canvas>
      <ambientLight />
      <Suspense fallback={null}>
        <Model />
      </Suspense>
      <OrbitControls />
    </Canvas>
  )
}

useGLTF (Drei)

The recommended way to load GLTF/GLB models.

Basic Usage

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

function Model() {
  const gltf = useGLTF('/models/robot.glb')

  // gltf contains:
  // - scene: THREE.Group (the main scene)
  // - nodes: Object of named meshes
  // - materials: Object of named materials
  // - animations: Array of AnimationClip

  return <primitive object={gltf.scene} />
}

Using Nodes and Materials

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

  return (
    <group>
      {/* Use specific meshes */}
      <mesh
        geometry={nodes.Body.geometry}
        material={materials.Metal}
        position={[0, 0, 0]}
      />
      <mesh
        geometry={nodes.Head.geometry}
        material={materials.Plastic}
        position={[0, 1, 0]}
      />
    </group>
  )
}

With TypeScript (gltfjsx)

Generate typed components using gltfjsx:

npx gltfjsx model.glb --types
// Generated component
import { useGLTF } from '@react-three/drei'
import { GLTF } from 'three-stdlib'

type GLTFResult = GLTF & {
  nodes: {
    Body: THREE.Mesh
    Head: THREE.Mesh
  }
  materials: {
    Metal: THREE.MeshStandardMaterial
    Plastic: THREE.MeshStandardMaterial
  }
}

export function Model(props: JSX.IntrinsicElements['group']) {
  const { nodes, materials } = useGLTF('/model.glb') as GLTFResult

  return (
    <group {...props} dispose={null}>
      <mesh geometry={nodes.Body.geometry} material={materials.Metal} />
      <mesh geometry={nodes.Head.geometry} material={materials.Plastic} />
    </group>
  )
}

useGLTF.preload('/model.glb')

Draco Compression

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

function Model() {
  // Drei automatically handles Draco if the file is Draco-compressed
  const { scene } = useGLTF('/models/compressed.glb')
  return <primitive object={scene} />
}

// Or specify Draco decoder path
useGLTF.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/')

Preloading

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

// Preload at module level
useGLTF.preload('/models/robot.glb')
useGLTF.preload(['/model1.glb', '/model2.glb'])

function Model() {
  // Will be instant if preloaded
  const { scene } = useGLTF('/models/robot.glb')
  return <primitive object={scene} />
}

Processing Loaded Model

function Model() {
  const { scene } = useGLTF('/models/robot.glb')

  useEffect(() => {
    // Enable shadows on all meshes
    scene.traverse((child) => {
      if (child.isMesh) {
        child.castShadow = true
        child.receiveShadow = true
      }
    })
  }, [scene])

  return <primitive object={scene} />
}

useLoader (Core R3F)

For loading any Three.js asset.

Basic Texture Loading

import { useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'

function TexturedMesh() {
  const texture = useLoader(TextureLoader, '/textures/color.jpg')

  return (
    <mesh>
      <boxGeometry />
      <meshStandardMaterial map={texture} />
    </mesh>
  )
}

Multiple Assets

function MultiTexture() {
  const [colorMap, normalMap, roughnessMap] = useLoader(TextureLoader, [
    '/textures/color.jpg',
    '/textures/normal.jpg',
    '/textures/roughness.jpg',
  ])

  return (
    <mesh>
      <sphereGeometry args={[1, 64, 64]} />
      <meshStandardMaterial
        map={colorMap}
        normalMap={normalMap}
        roughnessMap={roughnessMap}
      />
    </mesh>
  )
}

With Extensions (Draco)

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

function Model() {
  const gltf = useLoader(GLTFLoader, '/model.glb', (loader) => {
    const dracoLoader = new DRACOLoader()
    dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')
    loader.setDRACOLoader(dracoLoader)
  })

  return <primitive object={gltf.scene} />
}

Progress Callback

function Model() {
  const gltf = useLoader(
    GLTFLoader,
    '/model.glb',
    undefined,  // extensions
    (progress) => {
      console.log(`Loading: ${(progress.loaded / progress.total) * 100}%`)
    }
  )

  return <primitive object={gltf.scene} />
}

Preloading

import { useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'

// Preload
useLoader.preload(TextureLoader, '/textures/color.jpg')
useLoader.preload(TextureLoader, ['/tex1.jpg', '/tex2.jpg'])

// Clear cache
useLoader.clear(TextureLoader, '/textures/color.jpg')

Drei Loader Hooks

useTexture

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

// Single
const texture = useTexture('/texture.jpg')

// Array
const [color, normal] = useTexture(['/color.jpg', '/normal.jpg'])

// Named object (spreads directly to material)
const textures = useTexture({
  map: '/color.jpg',
  normalMap: '/normal.jpg',
  roughnessMap: '/roughness.jpg',
})
<meshStandardMaterial {...textures} />

// With callback for configuration
const texture = useTexture('/texture.jpg', (tex) => {
  tex.wrapS = tex.wrapT = THREE.RepeatWrapping
  tex.repeat.set(4, 4)
})

// Preload
useTexture.preload('/texture.jpg')

useCubeTexture

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

function EnvMap() {
  const envMap = useCubeTexture(
    ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
    { path: '/textures/cube/' }
  )

  return (
    <mesh>
      <sphereGeometry />
      <meshStandardMaterial envMap={envMap} metalness={1} roughness={0} />
    </mesh>
  )
}

useEnvironment

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

// Preset
const envMap = useEnvironment({ preset: 'sunset' })
// Presets: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse

// Custom HDR file
const envMap = useEnvironment({ files: '/hdri/studio.hdr' })

// Cube map
const envMap = useEnvironment({
  files: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
  path: '/textures/',
})

useVideoTexture

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

function VideoPlane() {
  const texture = useVideoTexture('/video.mp4', {
    start: true,
    loop: true,
    muted: true,
    crossOrigin: 'anonymous',
  })

  return (
    <mesh>
      <planeGeometry args={[16/9 * 2, 2]} />
      <meshBasicMaterial map={texture} toneMapped={false} />
    </mesh>
  )
}

useFont

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

// Preload font
useFont.preload('/fonts/helvetiker.json')

function Text() {
  return (
    <Text3D font="/fonts/helvetiker.json" size={1} height={0.2}>
      Hello
      <meshStandardMaterial color="gold" />
    </Text3D>
  )
}

Suspense Patterns

Basic Suspense

import { Suspense } from 'react'

function Scene() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </Canvas>
  )
}

function Loader() {
  return (
    <mesh>
      <boxGeometry />
      <meshBasicMaterial color="gray" wireframe />
    </mesh>
  )
}

Loading Progress UI

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

function Loader() {
  const { active, progress, errors, item, loaded, total } = useProgress()

  return (
    <Html center>
      <div className="loader">
        <div className="progress-bar">
          <div style={{ width: `${progress}%` }} />
        </div>
        <p>{Math.round(progress)}% loaded</p>
        <p>Loading: {item}</p>
      </div>
    </Html>
  )
}

function App() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Scene />
      </Suspense>
    </Canvas>
  )
}

Drei Loader Component

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

function App() {
  return (
    <>
      <Canvas>
        <Suspense fallback={null}>
          <Scene />
        </Suspense>
      </Canvas>
      {/* HTML loading overlay */}
      <Loader />
    </>
  )
}

Other Model Formats

OBJ + MTL

import { useLoader } from '@react-three/fiber'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'

function OBJModel() {
  const materials = useLoader(MTLLoader, '/model.mtl')
  const obj = useLoader(OBJLoader, '/model.obj', (loader) => {
    materials.preload()
    loader.setMaterials(materials)
  })

  return <primitive object={obj} />
}

FBX

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

function FBXModel() {
  const fbx = useFBX('/model.fbx')

  return <primitive object={fbx} scale={0.01} />
}

// Preload
useFBX.preload('/model.fbx')

STL

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

function STLModel() {
  const geometry = useLoader(STLLoader, '/model.stl')

  return (
    <mesh geometry={geometry}>
      <meshStandardMaterial color="gray" />
    </mesh>
  )
}

PLY

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

function PLYModel() {
  const geometry = useLoader(PLYLoader, '/model.ply')

  useEffect(() => {
    geometry.computeVertexNormals()
  }, [geometry])

  return (
    <mesh geometry={geometry}>
      <meshStandardMaterial vertexColors />
    </mesh>
  )
}

Clone for Multiple Instances

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

function Trees() {
  const { scene } = useGLTF('/models/tree.glb')

  return (
    <>
      <Clone object={scene} position={[0, 0, 0]} />
      <Clone object={scene} position={[5, 0, 0]} />
      <Clone object={scene} position={[-5, 0, 0]} />
      <Clone object={scene} position={[0, 0, 5]} scale={1.5} />
    </>
  )
}

Error Handling

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

function ModelWithErrorHandling() {
  return (
    <ErrorBoundary fallback={<FallbackModel />}>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </ErrorBoundary>
  )
}

function FallbackModel() {
  return (
    <mesh>
      <boxGeometry />
      <meshBasicMaterial color="red" wireframe />
    </mesh>
  )
}

Asset Caching

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

// Assets are automatically cached by URL
// Same URL = same asset instance

function Scene() {
  // These all reference the same cached asset
  const model1 = useGLTF('/model.glb')
  const model2 = useGLTF('/model.glb')
  const model3 = useGLTF('/model.glb')

  // Clear cache if needed
  useGLTF.clear('/model.glb')
}

Performance Tips

  1. Preload critical assets: Avoid loading during interaction
  2. Use Draco compression: Smaller file sizes
  3. Use LOD models: Different detail levels for distance
  4. Clone instead of reload: For multiple instances
  5. Lazy load non-critical: Load on demand
// Preload strategy
useGLTF.preload('/models/hero.glb')      // Critical
useTexture.preload('/textures/main.jpg')  // Critical

function LazyModel({ visible }) {
  // Only load when visible
  const { scene } = useGLTF(visible ? '/models/detail.glb' : null)
  return scene ? <primitive object={scene} /> : null
}

See Also

  • r3f-animation - Playing loaded animations
  • r3f-textures - Texture configuration
  • r3f-materials - Materials from loaded models

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

30.45%
按下载量换算1,019

Cursor

24.87%
按下载量换算832

Codex

16.61%
按下载量换算556

Gemini CLI

10.92%
按下载量换算365

Antigravity

6.64%
按下载量换算222

OpenCode

3.65%
按下载量换算122

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills