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

Three.js鼠标悬停高亮球体功能异常:无法切换及恢复颜色

Fixing Stuck Highlight & Unresponsive Raycasting in Three.js

Let's get that hover highlight working properly! I’ve gone through your code and found three main issues causing the stuck state and unresponsive raycasting:

1. Local Variable Shadowing Breaks State Persistence

In your render method, you’re creating local variables (highlighted, intersectHighlighted) that shadow the reactive data properties. When you update these local variables, you’re not actually modifying the component’s state—so the next render cycle will just use the old values again.

Fix: Remove the local variable declarations and directly work with this.highlighted (you don’t even need to store intersectHighlighted in data, since it’s recalculated every frame).

2. Incorrect Condition in the Else Block

Your else condition else if (intersectHighlighted !== this.spheres.object) doesn’t make sense—intersectHighlighted is an array of raycast hits, and this.spheres is your array of sphere objects. They’ll never match, so the else block never triggers correctly.

Fix: Replace it with a simple check for intersectHighlighted.length === 0—this means no spheres are under the mouse, so we should reset the highlight.

3. Wrong Event Listener for Mouse Tracking

You’re using mouseover, which only fires once when the mouse enters the element. To track mouse movement across the scene, you need mousemove instead. You also duplicated the mouseover listener, which is unnecessary.

Fix: Update the event listener to use mousemove, and remove the duplicate binding.

Modified Code Snippet

Here’s the fixed version of your key methods:

init() {
  // ... (keep your existing setup code)
  // Replace mouseover with mousemove, remove duplicate listener
  map.addEventListener('mousemove', this.mouseOverScene, false);
},
mouseOverScene (event) {
  event.preventDefault();
  let rect = event.target.getBoundingClientRect();
  let x = event.clientX - rect.left;
  let y = event.clientY - rect.top;
  this.mouse.x = (x / this.mapWidth) * 2 - 1;
  this.mouse.y = -(y / this.mapHeight) * 2 + 1;
  // No need to call setFromCamera here—we'll do it in render
},
render() {
  // Calculate raycast hits every frame
  this.rayCaster.setFromCamera(this.mouse, this.camera);
  const intersects = this.rayCaster.intersectObjects(this.spheres);

  if (intersects.length > 0) {
    const hoveredSphere = intersects[0].object;
    if (this.highlighted !== hoveredSphere) {
      // Reset previous highlighted sphere if exists
      if (this.highlighted) {
        this.highlighted.material.color.setHex(this.highlighted.currentHex);
      }
      // Highlight new sphere
      this.highlighted = hoveredSphere;
      this.highlighted.currentHex = hoveredSphere.material.color.getHex();
      this.highlighted.material.emissive.setHex(0xff0000);
    }
  } else {
    // No spheres hovered—reset highlight
    if (this.highlighted) {
      this.highlighted.material.color.setHex(this.highlighted.currentHex);
      this.highlighted = null;
    }
  }

  this.renderer.render(this.scene, this.camera);
}

Quick Notes

  • I removed the unnecessary intersectHighlighted data property since we recalculate the raycast hits every frame in render.
  • Moved rayCaster.setFromCamera to render to ensure it uses the latest mouse position every frame.
  • Cleaned up the logic flow to make it more readable and ensure the highlight resets correctly when the mouse leaves all spheres.

This should fix the stuck highlight and make the raycasting respond properly as you move the mouse between spheres!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:49:13