英文:
react-three-fiber: How to capture events ANYWHERE in <Canvas />?
问题
我正在尝试使用react-three-fiber
创建一个3D体验,在这个体验中用户可以与3D画布的任何部分进行交互,包括与物体相交的画布上的点,以及射线上没有任何交点的点。
这意味着我不能使用内置在<mesh />
等元素中的指针事件抽象,因为这些指针事件仅捕获与物体相交的点。
我尝试将处理程序附加到<Canvas onMouseDown={...} />
,但是我无法从那里访问THREE的内部,因为由onMouseDown
传递的event
不包含它们,并且useThree
钩子必须在树中更深层次才能访问THREE的React上下文。
所以我还尝试创建一个嵌套在<Canvas />
内的组件(如下所示),在那里我可以使用useThree
钩子:
<Canvas>
<MouseHandler>
...
<mesh />
...
</MouseHandler>
</Canvas>
export function MouseHandler({ children }) {
const { Camera } = useThree()
return <Html><div onMouseDown={...}>{children}</div></Html>
}
...但是然后react-three-fiber会抱怨我在HTML对象内有THREE对象。
有没有其他方法可以解决这个问题的建议?
英文:
I'm trying to create a 3D experience using react-three-fiber
where the user can interact with any part of the 3D canvas, including points on the canvas that both (a) intersect an object, and (b) where there is nothing intersecting the ray at all.
This means I can't use the pointer events abstractions built into <mesh />
etc., as those pointer events ONLY capture points that intersect objects.
I tried attaching handlers to the <Canvas onMouseDown={...} />
, however I'm unable to access the THREE internals from there as the event
passed by onMouseDown
does not contain them, and the useThree
hook must be deeper in the tree to access the THREE react context.
So I also tried creating a component nested inside <Canvas />
(see below) where I'd be able to use the useThree
hook:
<Canvas>
<MouseHandler>
...
<mesh />
...
</MouseHandler>
</Canvas>
export function MouseHandler({ children }) {
const { Camera } = useThree()
return <Html><div onMouseDown={...}>{children}</div></Html>
}
...but then react-three-fiber complains that I have THREE objects inside HTML objects.
Anyone have any suggestions on how else I might be able to solve this?
答案1
得分: 0
这似乎不是react-three-fiber
通常支持的用例,所以我最终采取了以下方法来处理,使用React Refs从树的深层中提取我需要的三维对象的"指针"。
const threeRef = useRef()
<MouseHandler threeRef={threeRef}>
<Canvas>
<ThreeConnect threeRef={threeRef}>
...
<mesh />
...
</ThreeConnect>
</Canvas>
</MouseHandler>
...
export function MouseHandler({ threeRef, children }) {
const { Camera } = threeRef.current
return <Html><div onMouseDown={...}>{children}</div></Html>
}
...
export default function ThreeConnect({ children, threeRef }) {
const { scene, camera } = useThree()
useEffect(() => {
threeRef.current = {
...threeRef.current,
camera,
scene,
}
}, [scene, camera])
return <>{children}</>
}
希望这对你有所帮助。
英文:
Doesn't feel like a common enough use case that react-three-fiber
would ever support, so what I ended up doing was hack it like this, using React Refs to yank a "pointer" to the three objects I needed from deeper into the tree.
const threeRef = useRef()
<MouseHandler threeRef={threeRef}>
<Canvas>
<ThreeConnect threeRef={threeRef}>
...
<mesh />
...
</ThreeConnect>
</Canvas>
</MouseHandler>
...
export function MouseHandler({ threeRef, children }) {
const { Camera } = threeRef.current
return <Html><div onMouseDown={...}>{children}</div></Html>
}
...
export default function ThreeConnect({ children, threeRef }) {
const { scene, camera } = useThree()
useEffect(() => {
threeRef.current = {
...threeRef.current,
camera,
scene,
}
}, [scene, camera])
return <>{children}</>
}
答案2
得分: 0
你可以将行为附加到网格对象的onPointerMissed
属性上,附加的处理程序将在画布上引发的与该网格不相交的事件时触发。
处理程序将接收到一个PointerEvent,其中有一个pointerId属性,但不会有一个eventObject属性。
因此,如果你可以在所有物体周围放置一个外部网格,并将行为附加到其opPointerMissed属性,那么你将处理场景中未被任何对象捕获的任何点击事件。
英文:
You can attach behavior to the onPointerMissed
prop of a mesh object, and the attached handler will fire whenever an event is raised on that canvas that does not intersect with that mesh.
The handler will receive a PointerEvent, having a pointerId property, though it will not have an eventObject property.
So if you could somehow afford to have an outer mesh around everything, and attach behavior to its opPointerMissed prop, then you'd handle any click that wasn't caught by any of the objects in the scene.
答案3
得分: -1
需要在<mesh>
中添加onMouseDown
以捕获与对象相交的点。
并在<Canvas>
中添加onPointerMissed
以捕获未与任何对象相交的情况。
英文:
You need add onMouseDown in <mesh>
for capture points that intersect objects.
And add onPointerMissed in <Canvas>
for capture nothing intersecting.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论