Three.js
- 官网:https://threejs.org
- 参考:
- GitHub 地址 https://github.com/mrdoob/three.js
- Stack Overflow https://stackoverflow.com/questions/tagged/three.js
- Intro to WebGL with Three.js http://davidscottlyons.com/threejs-intro/
- three.js 在线编辑器https://threejs.org/editor/
cnpm i --save three
cnpm i --save-dev @types/three
- 引入控件
cnpm i --save three-orbitcontrols-ts (另一种方式: 用来支持鼠标的交互行为的库)
import { OrbitControls } from 'three-orbitcontrols-ts';
- 建议使用下面的方式
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
react 中使用
-
大概流程
a. 创建一个场景实例 scene,是放置物体的空间 b. 创建一个摄像机 camera,通过设置位置等去观察场景中的物体 c. 创建一个渲染器 render,将渲染器的节点添加到容器中, 这一步很重要 d. 创建控制器 controls。 e. 配置灯光。 f. 创建模型和材质。 g. 添加动画。
-
demo
import React, { Component } from 'react'; import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; export default class SimpleScene extends Component { private renderer: any; private scene: any; private camera: any; private mesh: any; private controls: any; componentDidMount() { this.init(); this.animate(); } init = () => { // 生成场景 const scene = new THREE.Scene(); this.scene = scene; // 设置相机 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000, ); this.camera = camera; // 生成模型: 立方缓冲几何体(BoxGeometry) const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x049ef4, }); const mesh = new THREE.Mesh(geometry, material); this.mesh = mesh; scene.add(mesh); camera.position.set(3, 3, 3); camera.lookAt(mesh.position); // 设置灯光 const pointLight = new THREE.PointLight(0xff0000, 1); pointLight.position.set(3, 2, 1); scene.add(pointLight); // 环境光会均匀的照亮场景中的所有物体 const ambientLight = new THREE.AmbientLight(0xcccccc, 0.5); scene.add(ambientLight); // 渲染 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.render(scene, camera); this.renderer = renderer; const threeMain = document.getElementById('container'); threeMain?.appendChild(renderer.domElement); // 添加控制器 const controls = new OrbitControls(this.camera, this.renderer.domElement); controls.addEventListener('change', this.handleControl); this.controls = controls; }; handleControl = () => { this.renderer.render(this.scene, this.camera); }; // 添加动画,自己转动 animate = () => { requestAnimationFrame(this.animate); this.mesh.rotation.y += 0.02; this.renderer.render(this.scene, this.camera); }; componentWillUnmount() { // 移除所有的事件监听 this.controls.dispose(); } render() { return <div id="container"></div>; } }
学习案例demo,碰到的问题点
-
使用 GLTFLoader 将.glTF 文件加载到 three.js 中
- err: Unexpected token < in JSON at position 0
路径问题: new GLTFLoader() -> 改成:new GLTFLoader().setPath(‘/’); - err: Uncaught SyntaxError: Unexpected token ‘<’ (at
需要指向公共路径问题
- umirc.ts: publicPath: ‘/public/’,
- const loader = new GLTFLoader().setPath(‘/public/’);
- err: Unexpected token < in JSON at position 0
-
threejs 没有渲染任何东西
首先:注意调整后记得检查一致 const container = document.getElementById('container'); <div id="container" /> 其次:排查发现, 放在外层函数的原因:此时dom节点加载还未 - const container = document.getElementById('container'); - 放在里面即可 const initThree = () => { ... const container = document.getElementById('container'); ... }