使用Three.js模块加载3D模型遇OrbitControls构造函数错误求助
问题修复方案
错误根源
- 模块导入的
OrbitControls/GLTFLoader是独立导出的类,不属于THREE命名空间,不能用THREE.OrbitControls形式调用 OrbitControls实例化需要传入渲染器DOM元素作为第二个参数,否则无法响应交互- 事件绑定错误,不能直接把
renderer传给change事件,需绑定渲染函数 - 未声明全局变量,导致作用域问题
修改后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <link rel="stylesheet" type="text/css" href="assets/styles/style.css" /> <script type="importmap"> { "imports": { "three": "./assets/scripts/three.js-master/build/three.module.js", "three/examples/jsm/controls/OrbitControls": "./assets/scripts/three.js-master/examples/jsm/controls/OrbitControls.js", "three/examples/jsm/loaders/GLTFLoader": "./assets/scripts/three.js-master/examples/jsm/loaders/GLTFLoader.js" } } </script> </head> <body> <script type="module"> import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; let scene, camera, renderer, controls, hlight, directionalLight, light, light2, light3, light4, car; function init() { scene = new THREE.Scene(); console.log(scene); scene.background = new THREE.Color(0xdddddd); camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 5000 ); camera.rotation.y = (45 / 180) * Math.PI; camera.position.x = 800; camera.position.y = 100; camera.position.z = 1000; // 先创建渲染器,确保OrbitControls能获取DOM元素 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 正确实例化OrbitControls controls = new OrbitControls(camera, renderer.domElement); // 绑定change事件触发渲染 controls.addEventListener("change", () => renderer.render(scene, camera)); hlight = new THREE.AmbientLight(0x404040, 100); scene.add(hlight); directionalLight = new THREE.DirectionalLight(0xffffff, 100); directionalLight.position.set(0, 1, 0); directionalLight.castShadow = true; scene.add(directionalLight); light = new THREE.PointLight(0xc4c4c4, 10); light.position.set(0, 300, 500); scene.add(light); light2 = new THREE.PointLight(0xc4c4c4, 10); light2.position.set(500, 100, 0); scene.add(light2); light3 = new THREE.PointLight(0xc4c4c4, 10); light3.position.set(0, 100, -500); scene.add(light3); light4 = new THREE.PointLight(0xc4c4c4, 10); light4.position.set(-500, 300, 500); scene.add(light4); // 正确使用导入的GLTFLoader let loader = new GLTFLoader(); loader.load( "./assets/Model_3D/Car/scene.gltf", function (gltf) { car = gltf.scene.children[0]; car.scale.set(0.5, 0.5, 0.5); scene.add(gltf.scene); animate(); } ); } function animate() { // 更新控件状态,保证交互流畅 controls.update(); renderer.render(scene, camera); requestAnimationFrame(animate); } // 监听窗口大小变化,自适应调整 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); init(); </script> </body> </html>
关键修改说明
- 声明所有用到的变量,避免全局作用域污染
- 调整渲染器创建顺序,确保
OrbitControls能获取到DOM元素 - 直接使用导入的
OrbitControls/GLTFLoader类,去掉THREE前缀 - 修复
OrbitControls的事件绑定逻辑,触发正确的渲染操作 - 在动画循环中添加控件更新,保证交互时画面实时响应
- 新增窗口尺寸监听,适配屏幕变化
内容的提问来源于stack exchange,提问作者Justin Jari
相关产品推荐
相关产品推荐

