Three.js TransformControls调用attach方法报TypeError错误咨询
问题现象
在Angular项目中引入TransformControls后,按如下代码初始化实例、绑定事件并调用attach方法绑定模型:
const geometry = new THREE.BoxGeometry(200, 200, 200); const material = new THREE.MeshLambertMaterial({ transparent: false, opacity: 0.9, color: 0x00ff00 }); const mesh = new THREE.Mesh(geometry, material); this.control = new TransformControls(this.camera, this.renderer.domElement); this.control.addEventListener('change', this.renderer.render(this.scene, this.camera)); this.control.addEventListener('dragging-changed', function (event) { console.log("dragging-changed", event); this.controls.enabled = !event.value; }); this.scene.add(this.control); this.scene.add(mesh); this.control.reset(); this.control.attach(mesh);
调用attach时抛出如下类型错误:
Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'call') TypeError: Cannot read properties of undefined (reading 'call') at TransformControls.dispatchEvent (http://localhost:4200/vendor.js:245488:18) at TransformControls.set (http://localhost:4200/main.js:86:31) at TransformControls.attach (http://localhost:4200/main.js:555:21) at EditorComponent.<anonymous> (http://localhost:4200/main.js:8436:26) at Generator.next (<anonymous>) at http://localhost:4200/vendor.js:297508:71 at new ZoneAwarePromise (http://localhost:4200/polyfills.js:5737:21) at __awaiter (http://localhost:4200/vendor.js:297504:12) at EditorComponent.ngAfterViewInit (http://localhost:4200/main.js:8421:65) at callHook (http://localhost:4200/vendor.js:348386:14)
错误链路为attach -> set -> dispatchEvent,触发无法读取undefined的call属性的报错。
问题原因
报错的核心原因有两个:
change事件绑定的参数不是合法回调函数:addEventListener第二个参数需要传入函数引用,代码中写的this.renderer.render(this.scene, this.camera)是立即执行的函数调用,执行返回值为undefined。事件触发时dispatchEvent会遍历所有绑定的回调,尝试调用每个回调的call方法执行逻辑,碰到undefined就会抛出读不到call属性的错误,这就是当前报错的直接来源。dragging-changed事件的回调this指向错误:用普通function定义事件回调时,事件触发时回调内部的this会指向TransformControls实例本身,而不是Angular组件实例,后续执行this.controls.enabled = !event.value时会找不到controls属性抛出二次错误。
修复方案
调整事件绑定逻辑,把change事件的传参改为箭头函数包裹的回调,传入函数引用而非立即执行结果;同时把dragging-changed的回调也改为箭头函数绑定组件实例的this指向,修复后代码如下:
const geometry = new THREE.BoxGeometry(200, 200, 200); const material = new THREE.MeshLambertMaterial({ transparent: false, opacity: 0.9, color: 0x00ff00 }); const mesh = new THREE.Mesh(geometry, material); this.control = new TransformControls(this.camera, this.renderer.domElement); // 箭头函数包裹,传入合法回调引用 this.control.addEventListener('change', () => { this.renderer.render(this.scene, this.camera); }); // 箭头函数绑定组件this,保证能正确访问组件实例属性 this.control.addEventListener('dragging-changed', (event) => { console.log("dragging-changed", event); this.controls.enabled = !event.value; }); this.scene.add(this.control); this.scene.add(mesh); this.control.reset(); this.control.attach(mesh);
修复后即可正常触发attach逻辑,事件回调也能正确访问组件上的其他控制器实例属性。
内容的提问来源于stack exchange,提问作者daniel
相关产品推荐
相关产品推荐

