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

Mesh跟随鼠标功能在滚动时失效问题求助

问题分析与解决方案

问题根源

你当前的鼠标位置映射逻辑只基于静态视口尺寸,完全没考虑相机沿Y轴滚动时的3D空间位移。state.mouse.y的取值范围是[-1, 1],对应视口的顶部到底部,但当相机移动后,视口底部对应的3D世界Y坐标已经改变,直接用state.viewport.height计算targetY会打破鼠标位置和3D空间的映射关系,最终导致mesh在视口底部失效跳回顶部。

修复代码

改用屏幕坐标转世界坐标的方式,通过Three.js的Vector3.unproject()方法,把鼠标的屏幕位置转换成3D世界中的目标位置,这样无论相机怎么移动,都能正确匹配鼠标与mesh的位置关系:

export const Example = () => {
    const ref = useRef();

    useFrame((state) => {
        // 创建基于鼠标位置的屏幕向量,z值控制深度(0=近平面,1=远平面,可按需调整)
        const mouseVector = new state.Three.Vector3(
            state.mouse.x,
            state.mouse.y,
            0.5
        );
        // 将屏幕向量转换为世界坐标
        mouseVector.unproject(state.camera);
        
        // 提取目标位置
        const targetX = mouseVector.x;
        const targetY = mouseVector.y;

        // 平滑过渡到目标位置
        ref.current.position.x += (targetX - ref.current.position.x) * 0.2;
        ref.current.position.y += (targetY - ref.current.position.y) * 0.2;
    });

    return (
        <mesh ref={ref}>
            <sphereGeometry />
            <meshNormalMaterial />
        </mesh>
    );
};

可选优化

如果需要让mesh保持固定的Z轴深度(不随鼠标深度变化),可以在转换后锁定Z坐标:

// 转换后固定Z轴位置
mouseVector.unproject(state.camera);
const targetX = mouseVector.x;
const targetY = mouseVector.y;
const fixedZ = ref.current.position.z; // 保留mesh原有Z位置

ref.current.position.x += (targetX - ref.current.position.x) * 0.2;
ref.current.position.y += (targetY - ref.current.position.y) * 0.2;
ref.current.position.z = fixedZ;

修改后,无论相机如何沿Y轴滚动,mesh都会准确跟随鼠标的3D空间位置,不会再出现跳变问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:52:20