threejs

📁 mengto/skills 📅 6 days ago
1
总安装量
1
周安装量
#53644
全站排名
安装命令
npx skills add https://github.com/mengto/skills --skill threejs

Agent 安装分布

replit 1
opencode 1
cursor 1
codex 1

Skill 文档

Three.js — WebGL 3D Scenes Skill

When to use

  • Real 3D: product spins, interactive hero scenes, shaders/material effects, 3D data viz
  • You need full control beyond “background effects”
  • You can budget time for asset pipeline + performance tuning

Core mental model

  • Create:
    • Scene (root graph)
    • Camera (Perspective/Orthographic)
    • Renderer (WebGLRenderer)
    • Mesh = Geometry + Material
    • Lights (if using non-unlit materials)
  • Render loop:
    • requestAnimationFrame(animate)
    • Update time-based animations, controls, mixers, then renderer.render(scene, camera)

Key APIs/patterns

  • Setup:
    • const renderer = new THREE.WebGLRenderer({ canvas, antialias, alpha })
    • renderer.setSize(width, height, false)
    • renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  • Camera:
    • camera.aspect = width / height; camera.updateProjectionMatrix()
  • Scene graph:
    • scene.add(object) / object.position/rotation/scale
  • Loading assets:
    • GLTFLoader (models), TextureLoader (images), DRACOLoader (compressed glTF)
  • Controls (common):
    • OrbitControls (debug/product), PointerLockControls (FPS), custom pointer handlers
  • Cleanup (important in SPAs):
    • geometry.dispose(), material.dispose(), texture.dispose(), renderer.dispose()
    • Remove event listeners; cancel RAF.

Common pitfalls

  • Not handling resize → stretched/cropped rendering
  • Too high devicePixelRatio → mobile GPU meltdown
  • Leaking WebGL resources (not disposing) → crashes after route changes
  • Loading huge textures/models → slow start; use compressed textures, Draco/KTX2, smaller maps
  • Using too many lights/shadows → expensive; fake lighting with baked textures when possible

Quick recipes

1) Minimal spinning cube

import * as THREE from "three";

const canvas = document.querySelector("#c");
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true });

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
camera.position.set(0, 0, 4);

const geom = new THREE.BoxGeometry(1, 1, 1);
const mat = new THREE.MeshStandardMaterial({ color: 0x7c3aed });
const mesh = new THREE.Mesh(geom, mat);
scene.add(mesh);

scene.add(new THREE.AmbientLight(0xffffff, 0.8));
const dir = new THREE.DirectionalLight(0xffffff, 0.8);
dir.position.set(2, 2, 2);
scene.add(dir);

function resize() {
  const w = canvas.clientWidth;
  const h = canvas.clientHeight;
  renderer.setSize(w, h, false);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  camera.aspect = w / h;
  camera.updateProjectionMatrix();
}
window.addEventListener("resize", resize);
resize();

function animate(t) {
  mesh.rotation.y = t * 0.0006;
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

2) Respect reduced motion

  • If prefers-reduced-motion: reduce, render a still frame (no RAF) or slow updates.

What to ask the user

  • Is this decorative (hero) or functional 3D (product viewer)?
  • Target devices: mobile? older iPhones?
  • Asset format availability (glTF, HDRI, textures) and file size constraints
  • Accessibility/reduced motion requirements