
可视化
Skill 文件
Skill
SKILL.md
SKILL.md
| name | threejs-3d |
|---|---|
| title | Three.js 3D 可视化 |
| description | 当用户需要构建通用 WebGL 3D 场景,或明确要求 Three.js 时,使用此 Skill。该库擅长:3D 场景、GLTF/GLB 模型、产品展示、几何体组合、3D 数据空间、粒子系统、3D 文字标注、灯光材质效果、交互式 3D 动画。不要用于标准二维图表、声明式 3D 商业图表,或科学数据的曲面、等值面和向量场分析。 |
Three.js 3D 可视化
在单个 HTML 文件中使用 Three.js 创建 WebGL 3D 场景。支持几何体、材质、光照、相机控制、动画循环。
加载方式
Three.js 支持两种 CDN 加载方式:
方式一:纯内联 script(仅核心库,无附加模块)
html
<script src="https://cdn.jsdmirror.com/npm/three@0.170.0/build/three.min.js"></script>加载后全局可用 THREE 对象。限制:OrbitControls、GLTFLoader 等附加模块从 r150 起只发布 ES module,无法通过普通 <script> 加载。
适用于:不需要鼠标控制/模型加载的简单场景(纯展示、粒子动画等)。
方式二:import map + ES module(推荐,支持所有附加模块)
html
<script type="importmap">{ "imports": { "three": "https://cdn.jsdmirror.com/npm/three@0.170.0/build/three.module.js", "three/addons/": "https://cdn.jsdmirror.com/npm/three@0.170.0/examples/jsm/" }}</script>然后在 <script type="module"> 中使用 import * as THREE from 'three'。
HTML 模板 A — 纯内联(无 OrbitControls)
html
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js 3D 场景</title> <script src="https://cdn.jsdmirror.com/npm/three@0.170.0/build/three.min.js"></script> <style> * { margin: 0; padding: 0; } body { overflow: hidden; } canvas { display: block; } </style></head><body> <script> // 1. 场景 const scene = new THREE.Scene(); scene.background = new THREE.Color(0xf0f0f0);
// 2. 相机 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(3, 3, 3); camera.lookAt(0, 0, 0);
// 3. 渲染器 const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement);
// 4. 光照 scene.add(new THREE.AmbientLight(0xffffff, 0.5)); const dirLight = new THREE.DirectionalLight(0xffffff, 1); dirLight.position.set(5, 10, 7); scene.add(dirLight);
// 5. 物体 const cube = new THREE.Mesh( new THREE.BoxGeometry(1, 1, 1), new THREE.MeshStandardMaterial({ color: 0x4A90E2 }) ); scene.add(cube); scene.add(new THREE.GridHelper(10, 10));
// 6. 动画循环 function animate() { requestAnimationFrame(animate); cube.rotation.y += 0.01; cube.rotation.x += 0.005; renderer.render(scene, camera); } animate();
// 7. 响应窗口缩放 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); </script></body></html>HTML 模板 B — import map(推荐,含 OrbitControls)
html
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js 3D 场景</title> <script type="importmap"> { "imports": { "three": "https://cdn.jsdmirror.com/npm/three@0.170.0/build/three.module.js", "three/addons/": "https://cdn.jsdmirror.com/npm/three@0.170.0/examples/jsm/" } } </script> <style> * { margin: 0; padding: 0; } body { overflow: hidden; } canvas { display: block; } </style></head><body> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 1. 场景 const scene = new THREE.Scene(); scene.background = new THREE.Color(0xf0f0f0);
// 2. 相机 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(3, 3, 3);
// 3. 渲染器 const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement);
// 4. 控制器(鼠标旋转/缩放/平移) const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true;
// 5. 光照 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(5, 10, 7); scene.add(directionalLight);
// 6. 物体 const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshStandardMaterial({ color: 0x4A90E2 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube);
// 地面网格辅助线 const gridHelper = new THREE.GridHelper(10, 10); scene.add(gridHelper);
// 7. 动画循环 function animate() { requestAnimationFrame(animate); cube.rotation.y += 0.01; controls.update(); renderer.render(scene, camera); } animate();
// 8. 响应窗口缩放 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); </script></body></html>核心概念
三要素
| 概念 | 说明 |
|---|---|
| Scene | 场景容器,承载所有 3D 对象 |
| Camera | 观察视角(PerspectiveCamera 透视 / OrthographicCamera 正交) |
| Renderer | WebGL 渲染器,将场景画到 canvas |
常用几何体
javascript
new THREE.BoxGeometry(w, h, d) // 立方体new THREE.SphereGeometry(r, seg, seg) // 球体new THREE.CylinderGeometry(rT, rB, h) // 圆柱new THREE.PlaneGeometry(w, h) // 平面new THREE.TorusGeometry(r, tube) // 圆环new THREE.ConeGeometry(r, h) // 圆锥常用材质
javascript
new THREE.MeshBasicMaterial({ color }) // 无光照,纯色new THREE.MeshStandardMaterial({ color }) // PBR 标准材质(推荐)new THREE.MeshPhongMaterial({ color }) // Phong 光照new THREE.MeshLambertMaterial({ color }) // Lambert 漫反射new THREE.MeshNormalMaterial() // 法线颜色(调试用)光照类型
javascript
new THREE.AmbientLight(color, intensity) // 环境光(均匀)new THREE.DirectionalLight(color, intensity) // 平行光(太阳)new THREE.PointLight(color, intensity, dist) // 点光源new THREE.SpotLight(color, intensity) // 聚光灯new THREE.HemisphereLight(sky, ground, int) // 半球光常见场景示例
加载 GLTF 模型
javascript
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const loader = new GLTFLoader();loader.load('model.glb', (gltf) => { scene.add(gltf.scene);});多个物体 + 颜色
javascript
const colors = [0x4A90E2, 0xE74C3C, 0x2ECC71, 0xF39C12, 0x9B59B6];for (let i = 0; i < 5; i++) { const mesh = new THREE.Mesh( new THREE.SphereGeometry(0.5, 32, 32), new THREE.MeshStandardMaterial({ color: colors[i] }) ); mesh.position.set(i * 1.5 - 3, 0, 0); scene.add(mesh);}文字标签 (CSS2DRenderer)
javascript
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
const labelRenderer = new CSS2DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight);labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = '0';labelRenderer.domElement.style.pointerEvents = 'none';document.body.appendChild(labelRenderer.domElement);
const div = document.createElement('div');div.textContent = '标签文本';div.style.color = '#333';const label = new CSS2DObject(div);label.position.set(0, 1.5, 0);cube.add(label);
// 在动画循环中也要渲染labelRenderer.render(scene, camera);粒子系统
javascript
const particleCount = 1000;const positions = new Float32Array(particleCount * 3);for (let i = 0; i < particleCount * 3; i++) { positions[i] = (Math.random() - 0.5) * 20;}const particleGeometry = new THREE.BufferGeometry();particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));const particleMaterial = new THREE.PointsMaterial({ color: 0x4A90E2, size: 0.05 });const particles = new THREE.Points(particleGeometry, particleMaterial);scene.add(particles);注意事项
- 必须有动画循环:
requestAnimationFrame+renderer.render()才能持续渲染。 - OrbitControls 需要 module:附加模块只提供 ES module 格式,必须用
type="module"script + import map。 - 光照必不可少:使用
MeshStandardMaterial等需要光照的材质时,场景必须有光源,否则全黑。 - 响应式:必须监听
resize事件更新 camera aspect 和 renderer size。 - 性能:复杂场景注意控制面数,使用
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))限制高 DPI。 - 颜色格式:使用十六进制数字
0xFF0000或new THREE.Color('#ff0000')。
Ln 1, Col 1MarkdownSpaces: 2
No errors