先说结论
监听mesh时会导致同一mesh下同一个位置,如果重叠着多个3D对象,点击事件会被触发多次。而监听3D对象只有这个对象会触发这个事件一次。而如果监听平面,则不会检测到mesh下其它重叠的对象。
技术架构
- react
- threejs
- @react-three/drei
- @react-three/fiber
场景
有这样一段代码,一个网格对象(mesh)中有一个平面(Plane),当我在网格上监听鼠标抬起事件时,被触发了三次:
tsx
const PerspectiveCameraZ = 500
/**
* 区域平面
*/
const SrAreaPlane: React.FC<SrAreaPlaneProps> = (props) => {
const { imageUrl } = props
const texture = useLoader(TextureLoader, isEmpty(imageUrl) ? defaultImage : imageUrl)
// 获取纹理的宽度和高度,固定宽度
const textureWidth = PerspectiveCameraZ
// 高度等比缩小
const textureHeight = (texture.image.height * PerspectiveCameraZ) / texture.image.width
return (
<mesh
onPointerUp={(event) => {
// ...
}}>
<Plane args={[textureWidth, textureHeight]}>
<meshBasicMaterial map={texture} side={DoubleSide} transparent={true} />
</Plane>
// 假设这里有更多的内容
</mesh>
)
后来排查原因得到了上文的结论,将事件监听移动到Plane上,问题就得到解决了。
这是个有意思的问题,值得分享。