How to get raycaster corrected when canvas is in a componenet?

Hi,
I am trying to measure the distance between two points in a scene.
Here is the reference I used: Raycaster Measurements - Three.js Tutorials.
It works fine when the canvas is only present, but when there are other components the ray is getting hit somewhere else. Initially I thought it was because I gave document.addEventListener("mousemove", onMouseMove, false); and changed document with canvas element. But there was no difference.

this is the function used for mouse move :

function onMouseMove(event) {
  event.preventDefault();

  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  if (drawingLine) {
    raycaster.setFromCamera(mouse, camera);
    intersects = raycaster.intersectObjects(pickableObjects, false);
    if (intersects.length > 0) {
      const positions = line.geometry.attributes.position.array;
      const v0 = new THREE.Vector3(positions[0], positions[1], positions[2]);
      const v1 = new THREE.Vector3(
        intersects[0].point.x,
        intersects[0].point.y,
        intersects[0].point.z
      );
      positions[3] = intersects[0].point.x;
      positions[4] = intersects[0].point.y;
      positions[5] = intersects[0].point.z;
      line.geometry.attributes.position.needsUpdate = true;
      const distance = v0.distanceTo(v1);
      measurementLabels[lineId].element.innerText = distance.toFixed(3) + "mm";
      measurementLabels[lineId].position.set(
        (v0.x + v1.x) / 2,
        (v0.y + v1.y) / 2,
        (v0.z + v1.z) / 2
      );
    }
  }
}

I would like to make the raycaster accurate.

Thanks,
Binoy

Some wild guesses:

You can attempt to use recursive mode to see if it’s a hierarchy issue.
raycaster.intersectObjects(pickableObjects, true)

if the ray hit something else, you should be able to log the result and check what’s interfering
console.log(intersects), maybe the mouse coordinate pick the wrong clientX / clientY I’m betting on that if you use nested elements.

if the ray doesn’t output anything, then it come from something else.
like the event itself not firing.

Instead of this

mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

try

mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;

In the second code example, it adjusts to the size of the canvas, instead of the browser window.

If your canvas is smaller than the document, and offset left and top some distance, you can try

const rect = renderer.domElement.getBoundingClientRect()
...
function onDocumentMouseMove(event) {
    ...
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
    ...
}

Also, If you are using the CSS2DRenderer to draw the labels over top, then make sure it also matches the dimensions of the canvas.

4 Likes

Thanks for the help, this worked