You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js技术问题:如何为2D场景添加带自定义属性的可点击图形

Three.js: Adding Custom Properties & Fixing Mesh Click Functionality

Hey there! Let's get your triangle mesh set up with custom properties and working click events. First, a quick heads-up: Three.js Mesh objects don't natively support the on('click') event you're trying to use—we'll need to use a Raycaster to detect clicks on 3D objects instead. Plus, adding custom properties is straightforward once you know the right way to do it without conflicting with Three.js internals.

Step 1: Fix Click Detection with Raycaster

Raycasting is how Three.js checks if a mouse click intersects with any 3D objects in your scene. Here's how to implement it:

First, declare these variables outside your mesh creation code (so they're accessible in event handlers):

let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();

Then, add a mouse click event listener to your window/canvas:

window.addEventListener('mousedown', onMouseDown);

function onMouseDown(event) {
  // Convert mouse position to normalized device coordinates (-1 to +1)
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  // Update the picking ray with the camera and mouse position
  raycaster.setFromCamera(mouse, camera); // Make sure 'camera' is your scene's camera

  // Calculate objects intersecting the picking ray
  const intersects = raycaster.intersectObjects(scene.children);

  // Check if we hit any objects
  if (intersects.length > 0) {
    const clickedMesh = intersects[0].object;
    console.log('Clicked mesh:', clickedMesh);
    // Here's where we'll access custom properties later!
  }
}

Step 2: Add Custom Properties to Your Mesh

Three.js provides a userData property on all objects specifically for storing custom data—this is the safest way to add your own properties without overwriting built-in Three.js functionality. You can also add direct properties, but userData is recommended.

Modify your mesh creation code to include custom properties:

var geometry = new THREE.Geometry();
geometry.vertices.push(
  new THREE.Vector3(50, 0, 90),
  new THREE.Vector3(130, 0, 95),
  new THREE.Vector3(74, 0, -50)
);
geometry.faces.push(new THREE.Face3(0, 1, 2));
// Important: For older Geometry (not BufferGeometry), update faces/vertices
geometry.computeFaceNormals();

var material = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.9, transparent: true }); // Add transparent: true for opacity to work
var mesh = new THREE.Mesh(geometry, material);

// Add custom properties using userData
mesh.userData = {
  id: 'triangle-001',
  name: 'Red Clickable Triangle',
  customData: {
    value: 42,
    description: 'My first interactive mesh'
  }
};

// Alternatively, add direct properties (not recommended, but works)
// mesh.myCustomId = 'triangle-001';

scene.add(mesh);

Step 3: Access Custom Properties on Click

Now update the onMouseDown function to access your custom properties when the mesh is clicked:

function onMouseDown(event) {
  // ... (previous code)

  if (intersects.length > 0) {
    const clickedMesh = intersects[0].object;
    console.log('Clicked mesh custom data:', clickedMesh.userData);
    console.log('Mesh name:', clickedMesh.userData.name);
    console.log('Custom value:', clickedMesh.userData.customData.value);

    // If you added direct properties:
    // console.log('Direct custom ID:', clickedMesh.myCustomId);
  }
}

Extra Tips for Improvement

  • Use BufferGeometry: THREE.Geometry is deprecated—for better performance, switch to THREE.BufferGeometry instead. Here's a quick conversion for your triangle:
    const geometry = new THREE.BufferGeometry();
    const vertices = new Float32Array([
      50, 0, 90,
      130, 0, 95,
      74, 0, -50
    ]);
    geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
    geometry.setIndex(new THREE.BufferAttribute(new Uint16Array([0, 1, 2]), 1));
    geometry.computeFaceNormals();
    
  • Optimize Raycasting: If you have many objects, add them to a group and pass group.children to intersectObjects instead of scene.children to narrow down the detection range.
  • Hover Effects: You can extend the raycasting logic to mousemove events to add hover states (e.g., changing material color when the mouse is over the mesh).

内容的提问来源于stack exchange,提问作者Giox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:33:00