You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:30:53