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

Three.js导入FBX模型组子网格实现鼠标悬停磁吸跟随效果咨询

Three.js 光标磁吸效果实现方案

1. 正确获取光标对应的世界坐标系位置

你当前的坐标计算逻辑仅适用于相机沿Z轴正对场景、所有物体均处于Z=0平面的特定场景,参数稍有变化就会出现坐标数值异常的问题。推荐使用Three.js内置的Raycaster(射线投射器)实现通用坐标获取,计算更稳定准确:

// 提前声明公用变量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// 如果你所有网格都在Z=0平面,提前定义检测平面,性能更高
const targetPlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
const worldMousePos = new THREE.Vector3();

function onMouseMove(event) {
  // 计算标准化设备坐标 (-1 到 1 区间)
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  // 更新射线
  raycaster.setFromCamera(mouse, camera);
  // 求射线和目标平面的交点
  raycaster.ray.intersectPlane(targetPlane, worldMousePos);
  // 此时worldMousePos就是光标在目标平面上的准确世界坐标
  console.log(worldMousePos);
}

如果你的模型组不在Z=0平面,修改targetPlane的参数匹配你的模型所在平面即可。

2. 实现网格磁吸平移效果

要实现类似导航项的弹性磁吸效果,需要先存储每个网格的初始位置,再在渲染循环中做插值缓动,避免直接修改位置导致的生硬感:

修改后的完整逻辑:

// 新增:存储所有可动网格的初始位置
const meshes = [];

// Load object and play a third-party animation
loader.load("Object_001.fbx", (object) => {
  mixer = new THREE.AnimationMixer(object);
  const action = mixer.clipAction(object.animations[0]);
  action.play();

  object.traverse((child) => {
    if (child.isMesh) {
      child.material.map = texture;
      child.material.needsUpdate = true;
      // 存储网格和它的初始位置
      meshes.push({
        mesh: child,
        originPos: child.position.clone()
      });
    }
  });
  scene.add(object);
});

// 射线相关变量
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const targetPlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
const worldMousePos = new THREE.Vector3();
// 磁吸强度参数,数值越大响应越快、缓动效果越弱
const magnetForce = 0.12;
// 最大磁吸偏移距离,避免网格移动过远
const maxOffset = 2;

function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  raycaster.ray.intersectPlane(targetPlane, worldMousePos);
}

wrapperElement.addEventListener("mousemove", onMouseMove);

// 新增:在你的渲染循环中更新网格位置
function animate() {
  requestAnimationFrame(animate);
  
  // 更新每个网格的位置
  meshes.forEach(item => {
    // 计算目标位置:初始位置 + 指向光标位置的偏移,限制最大偏移量
    const targetX = item.originPos.x + THREE.MathUtils.clamp(worldMousePos.x - item.originPos.x, -maxOffset, maxOffset);
    const targetY = item.originPos.y + THREE.MathUtils.clamp(worldMousePos.y - item.originPos.y, -maxOffset, maxOffset);
    // 线性插值实现缓动效果
    item.mesh.position.x += (targetX - item.mesh.position.x) * magnetForce;
    item.mesh.position.y += (targetY - item.mesh.position.y) * magnetForce;
  });

  // 原有逻辑:更新动画混合器、渲染场景等
  if (mixer) mixer.update(clock.getDelta());
  renderer.render(scene, camera);
}
animate();

你可以根据实际效果调整magnetForce和maxOffset两个参数,匹配你需要的磁吸强度和移动范围。如果需要不同网格有不同的磁吸效果,也可以给每个网格单独配置这两个参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:24:02