React Three Fiber中如何实现点击悬停仅触发最近的物体?
解决React Three Fiber 3D物体交互穿透问题
根因说明
r3f的交互事件基于射线检测实现,默认会将射线命中的所有物体按距离视线由近到远的顺序依次触发对应事件,没有手动拦截的情况下就会出现前后物体同时响应点击、悬停的问题。
修复方案
在所有交互事件回调的第一行调用e.stopPropagation(),即可拦截事件向更远层的物体派发,仅最近的被命中物体响应交互。
修改后完整代码
import React, { useRef, useState } from 'react' import { Canvas, useFrame } from '@react-three/fiber' function Box(props) { const mesh = useRef() const [hovered, setHover] = useState(false) const [active, setActive] = useState(false) useFrame(() => { mesh.current.rotation.x = mesh.current.rotation.y += 0.01 }) return ( <mesh {...props} ref={mesh} scale={active ? 1.5 : 1} onClick={(e) => { e.stopPropagation() setActive(!active) }} onPointerOver={(e) => { e.stopPropagation() setHover(true) }} onPointerOut={(e) => { e.stopPropagation() setHover(false) }}> <boxGeometry args={[1, 1, 1]} /> <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} /> </mesh> ) } export default function App() { return ( <Canvas> <ambientLight intensity={0.5} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} /> <pointLight position={[-10, -10, -10]} /> <Box position={[1.2, 0.5, 0]} /> <Box position={[1.2, 0, 0]} /> </Canvas> ) }
补充说明
如果需要全局开启仅响应最近物体的交互逻辑,也可以在Canvas组件上配置射线检测参数,设置返回结果仅取第一个命中项,不过单组件内加stopPropagation的灵活度更高,更适配大部分业务场景。
内容的提问来源于stack exchange,提问作者DuckQueen
相关产品推荐
相关产品推荐

