[Yugong Series] August 2023 Three.js Topic-Events


foreword

An event is a specific thing or activity that happened at a certain time and place, often with importance and significance. Events can be anything, such as natural disasters, political events, cultural events, sports games, social events, and more. People usually regard events as important phenomena that attract widespread public attention and discussion, and can have a profound impact on social, political and cultural life.

In computer programs, an event is the occurrence of some specific action or state caused by a user action or by another program. For example, when the user clicks a button or a key on the keyboard, the corresponding event is fired. Programmers can write code to catch these events and then handle them. These events can be used to control the execution flow of the program, provide feedback to the user, or perform other custom actions. In Graphical User Interface (GUI) applications, event handling is very important as it makes the application more interactive and responsive. For example, when a user enters text in a text box, the application needs to capture the input event and save it into a corresponding variable for subsequent processing.

1. Events

1. Events in Three.js

Events in Three.js can be divided into two categories: browser events and Three.js custom events.

Browser events are common events that occur in Three.js scenarios, such as mouse clicks, mouse moves, keyboard presses, etc. These events can be captured by adding listeners (such as mouse listeners, keyboard listeners) in the Three.js scene.

Three.js custom events are events defined in Three.js' own framework, such as scene rendering events, object loading events, etc. These events can be caught by adding corresponding listeners.

Here is a simple code example that demonstrates how to listen for mouse click events in Three.js:

renderer.domElement.addEventListener('mousedown', function(event){
    
    
    console.log("Mouse clicked at X: " + event.clientX + ", Y: " + event.clientY);
});

In this code, we add a mousedown event listener to the three.js renderer dom element, which will output the coordinates of the mouse click when the user clicks the mouse.

2. Object selection event in Three.js

There are many methods for selecting 3D objects, some common methods are as follows:

  1. Ray-based detection: By sending a ray from the camera position, detecting the object that intersects with the ray, so as to determine whether an object is selected.

  2. Based on bounding box detection: Use a specific bounding box algorithm (such as the AABB algorithm) to create a box surrounding the object, and determine whether the object is selected by detecting whether the mouse is inside the box.

  3. Grid-based detection: For some regular, polygon-based objects (such as cubes, spheres, etc.), you can determine whether the object is selected by detecting whether it is inside its polygon.

  4. Color-based detection: For each object, set a unique color value for it, and determine whether an object is selected by detecting the color value of the mouse click position.

  5. Depth value-based detection: During rendering, record the rendered depth value for each object, and determine whether an object is selected by detecting the depth value of the mouse click position.

But in Three.js, you can use rays (Ray) to detect whether an object is selected. Generally speaking, we need to add a cursor to the scene, and then use rays to detect whether the cursor hits the target object every time the mouse moves. If it is hit, the selected event is triggered.

Here is a simple example showing how to implement object selection events in Three.js:

// 创建一个光标
var cursor = new THREE.Vector2();

// 监听鼠标移动事件,更新光标位置
document.addEventListener('mousemove', function(event) {
    
    
    // 计算光标位置(范围在-1到1之间)
    cursor.x = (event.clientX / window.innerWidth) * 2 - 1;
    cursor.y = - (event.clientY / window.innerHeight) * 2 + 1;
});

// 监听点击事件,检查是否选中物体
document.addEventListener('click', function(event) {
    
    
    // 定义射线
    var raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(cursor, camera);

    // 检查射线是否与物体相交
    var intersects = raycaster.intersectObjects(scene.children);

    // 如果存在相交对象
    if (intersects.length > 0) {
    
    
        // 触发选中事件
        var selectedObject = intersects[0].object;
        // Do something with the selected object
    }
});

In this example, we first create a cursor (cursor), then listen for mouse movement events, and update the cursor position. In the click event, we use a raycaster to detect if the cursor hits any object in the scene. If there is an intersecting object (intersects.length > 0), we can trigger selection events, such as changing the object color, rotating, etc. It should be noted that if there are multiple objects in the scene, we need to traverse (intersects) to determine which object is selected.

3. Case

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>
</head>
<body>

</body>
</html>

<script>
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(0,0,20);

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  // 添加一个立方体
  // 定义了一个立方体的对象
  const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);

  // 创建材质

  const lambert = new THREE.MeshLambertMaterial({
      
       color: 0xff0000 })
  const basic = new THREE.MeshBasicMaterial({
      
       wireframe: true })

  const cube = new THREE.Mesh(cubeGeometry, lambert)

  cube.rotation.set(0.4, 0.4, 0);
  cube.position.x = -4;
  // 添加到场景里
  cube.name = 'cube'
  scene.add(cube);

  const sphereGeometry = new THREE.SphereGeometry(2, 10, 10)
  const sphere = new THREE.Mesh(sphereGeometry, lambert)
  sphere.position.x = 4;
  sphere.name = 'sphere'
  scene.add(sphere);

  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-10,10,90);
  scene.add(spotLight);

  document.onclick = function (event) {
      
      
    // 获取到浏览器坐标
    const x = (event.clientX / window.innerWidth) * 2 - 1;
    const y = -(event.clientY / window.innerHeight) * 2 + 1;

    // 创建设备坐标(三维)
    const standardVector = new THREE.Vector3(x, y, 0.5);

    // 转化为世界坐标
    const worldVector = standardVector.unproject(camera);

    // 做序列化
    const ray = worldVector.sub(camera.position).normalize();

    // 如何实现点击选中
    // 创建一个射线发射器,用来发射一条射线
    const raycaster = new THREE.Raycaster(camera.position, ray);

    // 返回射线碰撞到的物体
    const intersects = raycaster.intersectObjects(scene.children, true);
    console.log(intersects)
    let point3d = null;
    if (intersects.length) {
      
      
      point3d = intersects[0]
    }
    if (point3d) {
      
      
      alert(point3d.object.name)
    }
  }

  const animation = () => {
      
      
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);
  }
  animation()
</script>

insert image description here

Guess you like

Origin blog.csdn.net/aa2528877987/article/details/132210005