javascript - Detectar objeto pinchado en THREE.js
(4)
Echa un vistazo a este:
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 5000);
var object; //your object
document.addEventListener(''mousedown'', onMouseDown, false);
function onMouseDown(e) {
var vectorMouse = new THREE.Vector3( //vector from camera to mouse
-(window.innerWidth/2-e.clientX)*2/window.innerWidth,
(window.innerHeight/2-e.clientY)*2/window.innerHeight,
-1/Math.tan(22.5*Math.PI/180)); //22.5 is half of camera frustum angle 45 degree
vectorMouse.applyQuaternion(camera.quaternion);
vectorMouse.normalize();
var vectorObject = new THREE.Vector3(); //vector from camera to object
vectorObject.set(object.x - camera.position.x,
object.y - camera.position.y,
object.z - camera.position.z);
vectorObject.normalize();
if (vectorMouse.angleTo(vectorObject)*180/Math.PI < 1) {
//mouse''s position is near object''s position
}
}
Tengo una escena de THREE.js donde aparecen muchos elementos, y necesito detectar en qué objeto está haciendo clic el usuario.
Lo que he hecho hasta ahora es lo siguiente. La cámara no se mueve demasiado, solo cambia la posición vertical en una cantidad limitada, siempre mirando hacia el mismo punto. Mi método aproximado es el siguiente:
- Tomo las coordenadas si el clic relativo al lienzo
- Los traduzco en coordenadas horizontales y verticales en la escena webGL por medio de un simple cambio de escala, y agrego una coordenada Z que está lo suficientemente lejos.
- Tomo un rayo horizontal a partir del punto anterior, construido por THREE.Ray ()
- Uso ray.intersectObjects () para encontrar el primer elemento a lo largo del rayo.
Este método funciona aproximadamente, pero a veces está a unos pocos píxeles del punto real.
¿Existe una técnica más confiable para averiguar el objeto en el que un usuario ha hecho clic?
Me encontré con problemas al intentar implementar esto para un lienzo que no ocupa todo el ancho y la altura de la pantalla. Aquí está la solución que encontré funciona bastante bien.
Inicializa todo en un lienzo existente:
var init = function() {
var canvas_model = document.getElementById(''model'')
var viewSize = 50 // Depending on object size, canvas size etc.
var camera = new THREE.OrthographicCamera(-canvas_model.clientWidth/viewSize, canvas_model.clientWidth/viewSize, canvas_model.clientHeight/viewSize, -canvas_model.clientHeight/viewSize, 0.01, 2000),
}
Agrega un detector de eventos al lienzo:
canvas_model.addEventListener(''click'', function(event){
var bounds = canvas_model.getBoundingClientRect()
mouse.x = ( (event.clientX - bounds.left) / canvas_model.clientWidth ) * 2 - 1;
mouse.y = - ( (event.clientY - bounds.top) / canvas_model.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
// Do stuff
}
}, false)
O para un evento ''touchstart'', cambie las líneas que calculan mouse.x y mouse.y en:
mouse.x = ( (event.touches[0].clientX - bounds.left) / canvas_model.clientWidth ) * 2 - 1;
mouse.y = - ( (event.touches[0].clientY - bounds.top) / canvas_model.clientHeight ) * 2 + 1;
Verifica la intersección del mouse y cualquiera de los cubos en el espacio 3d y altera su color. Tal vez this te ayude.
Depende del tipo de cámara que estés usando.
1) PerspectiveCamera : está bien el enlace que proporciona Mr.doob .
2) OrthographicCamera : es bastante diferente:
var init = function() {
camera = new THREE.OrthographicCamera( SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, NEAR, FAR);
document.addEventListener( ''mousedown'', onDocumentMouseDown, false );
}
function onDocumentMouseDown( e ) {
e.preventDefault();
var mouseVector = new THREE.Vector3();
mouseVector.x = 2 * (e.clientX / SCREEN_WIDTH) - 1;
mouseVector.y = 1 - 2 * ( e.clientY / SCREEN_HEIGHT );
var raycaster = projector.pickingRay( mouseVector.clone(), camera );
var intersects = raycaster.intersectObject( TARGET );
for( var i = 0; i < intersects.length; i++ ) {
var intersection = intersects[ i ],
obj = intersection.object;
console.log("Intersected object", obj);
}
}