【问题标题】:how to get clicked element in THREE.js如何在 THREE.js 中获取被点击的元素
【发布时间】:2011-12-20 12:46:50
【问题描述】:

假设我在画布中有一些元素,它们可能会相互覆盖。当点击一个点时,我怎样才能得到那个元素?

更新:这个演示很有帮助: http://mrdoob.github.com/three.js/examples/canvas_interactive_cubes.html

【问题讨论】:

标签: javascript html three.js


【解决方案1】:

使用以下代码。这将允许您添加点击事件并在发生这种情况时执行您需要的操作。你可以查看页面的源代码,看看他们在做什么,我是从哪里得到这个代码的。

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 );
    }
    */
}

【讨论】:

  • projector 变量在哪里声明和初始化?
  • 我在答案中添加了var projector = new THREE.Projector();,没有进行测试运行或其他任何操作,但我在自己的代码中使用了几乎相同的逻辑,该逻辑取自 ThreeJS 示例。
  • vector.subSelf 不再存在。现在应该是vector.sub。此外,unprojectVector 现在是 unproject
【解决方案2】:

您链接到的示例为此提供了一个简单的 API。

把它放在你的 HTML 中。您必须download the script 并确保它已加载。

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

然后,在您的网格对象上,调用以下命令:

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

或者一个更有趣的例子,可以平滑地为对象的旋转和颜色设置动画:

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();
})

【讨论】:

  • 它说 Uncaught TypeError: Object [object Object] has no method 'on' mazeJs.js:198
  • @Rickie,你的mesh 实例的类型是什么?
  • 这个脚本真的很酷,我很想使用它,但我也收到一个错误:Uncaught TypeError: mesh.on is not a function.. var img = new THREE.MeshBasicMaterial({ map :THREE.ImageUtils.loadTexture('images/greg.jpg') }); var mesh = new THREE.Mesh(new THREE.PlaneGeometry(50, 50),img); --- 我想知道可能导致错误的原因
  • @Starfs,如果您尝试使用mesh.addEventListener('click', ... 而不是mesh.on('click', ...,会怎样?
  • 另外请务必阅读我链接到的脚本的文档。
【解决方案3】:

也许这个工具可以帮助你,一个全交互管理器,帮助three.js轻松绑定交互事件

更多细节见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);
})

【讨论】:

    【解决方案4】:

    Drew 使用 THREEx.domevents 的回答已过时。新 API 需要初始化一个 domEvents 对象,然后将带有相应事件侦听器的网格绑定到它。

    来自Github repo

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

    此外,它还可以在凉亭上使用!

    bower install threex.domevents
    

    编辑: 虽然没有记录,但也支持'touchstart''touchend' 和其他一些移动事件。如果支持移动设备,请务必查看这些内容,因为在某些设备上并不总是报告鼠标“点击”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 2022-07-19
      相关资源
      最近更新 更多