ThreeJS Como añadir evento click a objecto 3d obj Cargado

smonge82 - 16/08/2019 09:36
Buenos días,
He creado una página en la que carga diferentes objetos.obj con sus texturas.mtl. El problema es que intento agregarles el evento addEventListener para desarrollar una funcionalidad al hacer click sobre cada uno de ellos y aunque no me deja error ninguno, no me hace nada al pinchar sobre los objetos.

Soy nuevo en esto y supongo que no es tan sencillo pero la carga del objeto la había hecho de la siguiente forma:
var mtLLoader = new THREE.MTLLoader();

mtLLoader.setMaterialOptions({ invertTrProperty: true });
mtLLoader.load(modelos/Carpeta.mtl,function(materiales){
materiales.preload();

var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materiales);
objLoader.load(modelos/Carpeta.obj,function(mesh){
mesh.scale.set(1,1,1);
mesh.dispatchEvent({ type: start, message: vroom vroom!});
mesh.addEventListener(click, function eventHandler(e) {
alert(hol);
}, false);
scene.add(mesh);
});
});
Gracias y un saludo.
LaUrA-28 - 04/01/2026 14:14
El problema principal es que estás intentando añadir el evento click directamente al objeto 3D (mesh), pero en Three.js necesitas usar un Raycaster para detectar clics sobre objetos en la escena 3D. El addEventListener que usas funciona para elementos DOM del navegador, no para objetos en el espacio 3D de WebGL.

Debes crear un Raycaster que proyecte un rayo desde la cámara hacia la posición del ratón en la pantalla. Luego compruebas qué objetos intersecta ese rayo.

Aquí está la solución actualizada. Primero, necesitas un listener de clic en el renderizador de Three.js (o en el elemento canvas). Dentro de esa función, calculas las coordenadas normalizadas del ratón y usas el Raycaster.

Declara un raycaster global: var raycaster = new THREE.Raycaster(); y un vector para el ratón: var mouse = new THREE.Vector2();

Luego, añade un event listener al canvas (o al renderer.domElement) para el evento 'click'. En ese listener, actualiza las coordenadas del ratón. Calcula el mouse.x y mouse.y en un rango de -1 a 1 basándote en la posición del clic en el canvas.

Después, establece el raycaster desde la cámara usando el vector del ratón. Usa el método intersectObjects() del raycaster, pasando el array de objetos que quieres comprobar (puede ser scene.children). Si el array de intersecciones tiene longitud, significa que has clickeado un objeto. Puedes acceder al objeto intersectado en intersection[0].object.

En tu código de carga, ya no pones el addEventListener en el mesh. En su lugar, asegúrate de que el objeto sea interactivo. Puedes hacer mesh.userData.clickable = true; para identificarlo más fácilmente. Luego en la función del raycaster, filtra los objetos o comprueba esta propiedad.

Ejemplo de código para el listener del clic:

function onMouseClick(event) {
// Calcula la posición del ratón en coordenadas normalizadas (-1 a +1)
mouse.x = (event.clientX / window.innerWidth) [i] 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) [/i] 2 + 1;

// Actualiza el raycaster con la cámara y la posición del ratón
raycaster.setFromCamera(mouse, camera);

// Calcula los objetos que intersecta el rayo
var intersects = raycaster.intersectObjects(scene.children, true);

// Si hay al menos una intersección, manejamos el clic
if (intersects.length > 0) {
// El primer objeto intersectado es el más cercano
var clickedObject = intersects[0].object;
// Puedes subir en el parent hasta encontrar el mesh principal si es necesario
alert('¡Objeto clickeado!');
// Aquí ejecutas la funcionalidad que necesites para ese objeto
}
}

// Añade el event listener al canvas
renderer.domElement.addEventListener('click', onMouseClick, false);

Recuerda que las coordenadas del ratón deben calcularse correctamente respecto al viewport del renderizador. Si tu canvas no ocupa toda la ventana, necesitarás ajustar el cálculo usando getBoundingClientRect().

Además, para que funcione bien, los materiales de tus objetos deben permitir el raycasting. Los materiales básicos de Three.js lo permiten por defecto. Si usas materiales personalizados, asegúrate de no tener activada la propiedad material.side = THREE.DoubleSide si no es necesario, pero generalmente no es un problema.

Esta es la forma estándar y actual de manejar clics en objetos 3D con Three.js.