简体   繁体   中英

how to get clicked element in THREE.js

Say I have some elements in the canvas, they may be overridden with each other. When clicking on a point, how can I get that very element?

update : this demo helps a lot: http://mrdoob.github.com/three.js/examples/canvas_interactive_cubes.html

Use the following code. This will allow you to add a click event and do what you need to when that happens. You can view the source of the page to see what they are doing which is were I got this code from.

document.addEventListener( 'mousedown', onDocumentMouseDown, false );

var projector = new THREE.Projector();

function onDocumentMouseDown( event ) {

    event.preventDefault();

    var vector = new THREE.Vector3(
        ( event.clientX / window.innerWidth ) * 2 - 1,
      - ( event.clientY / window.innerHeight ) * 2 + 1,
        0.5
    );
    projector.unprojectVector( vector, camera );

    var ray = new THREE.Ray( camera.position, 
                             vector.subSelf( camera.position ).normalize() );

    var intersects = ray.intersectObjects( objects );

    if ( intersects.length > 0 ) {

        intersects[ 0 ].object.materials[ 0 ].color.setHex( Math.random() * 0xffffff );

        var particle = new THREE.Particle( particleMaterial );
        particle.position = intersects[ 0 ].point;
        particle.scale.x = particle.scale.y = 8;
        scene.add( particle );

    }

    /*
    // Parse all the faces
    for ( var i in intersects ) {
        intersects[ i ].face.material[ 0 ].color
            .setHex( Math.random() * 0xffffff | 0x80000000 );
    }
    */
}

The example you link to has a simple API for this.

Put this in your HTML. You'll have to download the script and make sure it loads.

<script src='threex.domevent.js'></script>

Then, on your mesh object, call the following:

mesh.on('click', function()
{
    // response to click...
    mesh.scale.x *= 2;
});

Or a more interesting example that animates the rotation and color of an object smoothly:

mesh.on('click', function(event)
{
    var object3d = event.target,
        rotation, color;
    if (object3d.rotation.x < Math.PI / 4) {
        rotation = {x: Math.PI / 2};
        color = {r: 1, g: 0.5, b: 0};
    } else {
        rotation = {x: 0};
        color = {r: 0.5, g: 0.75, b: 0.25};
    }
    new TWEEN.Tween(object3d.rotation)
        .to(rotation, 800)
        .easing(TWEEN.Easing.Bounce.EaseOut)
        .start();
    new TWEEN.Tween(object3d.material.color)
        .to(color, 300)
        .easing(TWEEN.Easing.Quartic.EaseIn)
        .start();
})

maybe this tool can help you, a full-interaction manager, help three.js easy to binding interaction event

more detial see three.interaction

 import { Scene, PerspectiveCamera, WebGLRenderer, Mesh, BoxGeometry, MeshBasicMaterial } from 'three'; import { Interaction } from 'three.interaction'; const renderer = new WebGLRenderer({ canvas: canvasElement }); const scene = new Scene(); const camera = new PerspectiveCamera(60, width / height, 0.1, 100); // new a interaction, then you can add interaction-event with your free style const interaction = new Interaction(renderer, scene, camera); const cube = new Mesh( new BoxGeometry(1, 1, 1), new MeshBasicMaterial({ color: 0xffffff }), ); scene.add(cube); cube.cursor = 'pointer'; cube.on('click', function(ev) {}); cube.on('touchstart', function(ev) {}); cube.on('touchcancel', function(ev) {}); cube.on('touchmove', function(ev) {}); cube.on('touchend', function(ev) {}); cube.on('mousedown', function(ev) {}); cube.on('mouseout', function(ev) {}); cube.on('mouseover', function(ev) {}); cube.on('mousemove', function(ev) {}); cube.on('mouseup', function(ev) {}); // and so on ... /** * you can also listen at parent or any display-tree node, * source event will bubble up along with display-tree. */ scene.on('touchstart', ev => { console.log(ev); }) scene.on('touchmove', ev => { console.log(ev); }) 

Drew's answer using THREEx.domevents is outdated. The new API requires initializing a domEvents object and then bind meshes w/ corresponding event listeners to it.

From the Github repo :

var domEvents   = new THREEx.DomEvents(camera, renderer.domElement)
// ...
domEvents.addEventListener(mesh, 'click', function(event){
    console.log('you clicked on the mesh')
}, false)

Also, it's available on bower!

bower install threex.domevents

Edit: Though not documented, there is support for 'touchstart' , 'touchend' , and a few other mobile events as well. Be sure to look into these if supporting mobile, as mouse 'clicks' aren't always reported as such on some devices.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM