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

使用Three.js Raycaster实现鼠标移动碰撞检测时遇camera未定义错误

解决Three.js Raycaster鼠标移动碰撞检测时的"无法读取camera属性"错误

我希望在鼠标移动(MouseMove)后检测碰撞,使用Three.js的Raycaster实现,但出现以下错误:

无法读取未定义的属性(读取'camera')

代码如下:

bindIFrameMousemove(iframe){
  iframe.contentWindow.addEventListener('mousemove', function(event) {
    const mouse = new Vector2();
    var clRect = iframe.getBoundingClientRect();
    var evt = new CustomEvent('mousemove', {bubbles: true, cancelable: false});
    const clientX = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientX : event.clientX;
    const clientY = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientY : event.clientY;
    const x = ( clientX / window.innerWidth ) * 2 - 1;
    const y = - ( clientY / window.innerHeight ) * 2 + 1;
    iframe.dispatchEvent(evt);
    event.preventDefault();
    mouse.x= ( clientX / window.innerWidth ) * 2 - 1;
    mouse.y =  - ( clientY / window.innerHeight ) * 2 + 1;
    Raycaster.setFromCamera( mouse, this.context.camera );
    const intersects = Raycaster.getIntersectObjects(this.scene.children ,true );
    console.log(intersects)

    if (intersects.length > 0) {
      console.log("intersects !!");
    }
  });
};

错误原因

  1. this指向异常:addEventListener的普通回调函数中,this指向的是iframe.contentWindow,而非外部类/对象的上下文,导致this.context和this.scene均为undefined,读取camera属性时触发错误。
  2. Raycaster使用错误:Raycaster是Three.js的类,必须先实例化才能调用方法,直接用类调用setFromCamera不符合API规范。
  3. 方法名拼写错误:Three.js中获取相交对象的方法是intersectObjects,而非getIntersectObjects。

修复方案

方案一:用箭头函数绑定上下文

箭头函数会继承外部作用域的this,直接解决指向问题:

bindIFrameMousemove(iframe){
  // 实例化Raycaster
  const raycaster = new THREE.Raycaster();
  iframe.contentWindow.addEventListener('mousemove', (event) => {
    const mouse = new THREE.Vector2();
    var clRect = iframe.getBoundingClientRect();
    var evt = new CustomEvent('mousemove', {bubbles: true, cancelable: false});
    const clientX = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientX : event.clientX;
    const clientY = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientY : event.clientY;
    // 修正坐标计算:基于iframe自身宽高,避免窗口偏移问题
    const x = ((clientX - clRect.left) / clRect.width) * 2 - 1;
    const y = -((clientY - clRect.top) / clRect.height) * 2 + 1;
    iframe.dispatchEvent(evt);
    event.preventDefault();
    mouse.x = x;
    mouse.y = y;
    // 使用实例化的raycaster,this指向外部上下文
    raycaster.setFromCamera(mouse, this.context.camera);
    const intersects = raycaster.intersectObjects(this.scene.children, true);
    console.log(intersects)

    if (intersects.length > 0) {
      console.log("intersects !!");
    }
  });
};

方案二:提前保存外部this引用

如需兼容不支持箭头函数的环境,可在回调外部保存this的引用:

bindIFrameMousemove(iframe){
  const raycaster = new THREE.Raycaster();
  const self = this; // 保存外部上下文的this
  iframe.contentWindow.addEventListener('mousemove', function(event) {
    const mouse = new THREE.Vector2();
    var clRect = iframe.getBoundingClientRect();
    var evt = new CustomEvent('mousemove', {bubbles: true, cancelable: false});
    const clientX = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientX : event.clientX;
    const clientY = (window.TouchEvent && event instanceof TouchEvent) ? 
    event.changedTouches[0].clientY : event.clientY;
    // 修正坐标计算
    const x = ((clientX - clRect.left) / clRect.width) * 2 - 1;
    const y = -((clientY - clRect.top) / clRect.height) * 2 + 1;
    iframe.dispatchEvent(evt);
    event.preventDefault();
    mouse.x = x;
    mouse.y = y;
    // 使用保存的self访问外部上下文
    raycaster.setFromCamera(mouse, self.context.camera);
    const intersects = raycaster.intersectObjects(self.scene.children, true);
    console.log(intersects)

    if (intersects.length > 0) {
      console.log("intersects !!");
    }
  });
};

额外注意事项

  • 确保外部作用域中this.context.camera和this.scene已正确初始化,避免出现undefined。
  • 鼠标坐标计算需基于iframe的位置和宽高,否则会出现点击偏移问题。

内容的提问来源于stack exchange,提问作者Y Z

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:36:17