Reputation: 669
In my code I have two cubes, I want to add click event listener to them. for example alerting on which cube the user clicked. When I added the click event listener to the document it was worked perfectly, but when I added the same click event listener to the cube it isn't showing anything. Here is my part of code..
<script type = "text/javascript" src = "three.min.js"></script>
<script type="text/javascript">
var camera = new THREE.PerspectiveCamera(70,window.innerWidth/window.innerHeight,0.1,1000);
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.z=30;
var geometry = new THREE.CubeGeometry(10,10,10);
var material = new THREE.MeshBasicMaterial({color:0x778899});
var cube = new THREE.Mesh(geometry,material);
cube.addEventListener("mousedown", onDocumentMouseDown, false);
cube.position.x = -10;
scene.add(cube);
var cube1 = new THREE.Mesh(geometry,material);
cube.addEventListener("mousedown", onDocumentMouseDown, false);
cube1.position.x=10;
scene.add(cube1);
var render = function(){
var timer = Date.now()*-0.0002;
requestAnimationFrame(render);
camera.position.x = 30* Math.cos(timer);
camera.position.z = 30* Math.sin(timer);
camera.lookAt(scene.position);
renderer.render(scene,camera);
};
render();
function onDocumentMouseDown(event){
alert('hi');
}
</script>
Upvotes: 7
Views: 21299
Reputation: 93
Adding click listener for Three.js objects is not supported by default.
You should combine usage of Raycaster with mouse event:
export const addObjectClickListener = (
camera,
scene,
raycaster,
objectToWatch,
onMouseClick,
) => {
const objectToWatchId = objectToWatch.uuid;
let mouse = new THREE.Vector2();
document.addEventListener(
"click",
(event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
const isIntersected = intersects.find(
(intersectedEl) => intersectedEl.object.uuid === objectToWatchId
);
if (isIntersected) {
onMouseClick();
}
},
false
);
};
This expects few parameters:
You can do similar thing for hover & other events. Just be careful with performance, since you register new listener for global mouse event every time you call this function. So If you need to add many clickable objects you probably want to do it in other way.
Upvotes: 4
Reputation: 657
You could also use Threex.js' domEvents to add a listener to an object mesh.
var domEvents = new THREEx.DomEvents(camera, renderer.domElement);
domEvents.addEventListener(cube, 'mousedown', onDocumentMouseDown, false);
domEvents.addEventListener(cube1, 'mousedown', onDocumentMouseDown, false);
function onDocumentMouseDown(event){
if (event.target == cube)
//do stuff
}
Upvotes: 1
Reputation: 113
addEventListener
can only be used for DOM elements. See EventTarget.addEventListener()
If you want to select objects in a Three.js scene you should look into the Three.js Raycaster
The Raycaster basically sends a ray from the camera into the scene and returns an array of objects that intersect with the ray. To make use of the Raycaster you need to attach the addEventListener
to the window object or your Three.js canvas.
For example: window.addEventListener( 'mousemove', onMouseMove, false );
There are a lot of examples for using the Raycaster on the Three.js examples page.
Upvotes: 8