所有你可以使用的事件
Events 事件
实现了自己的 raycast 方法的 three.js 对象(如 meshes、lines 等)可以通过在它们上面声明事件来进行交互。我们支持指针事件、点击和滚轮滚动。这些事件包含浏览器事件以及 three.js 的事件数据(对象、点、距离等)。如果需要的话,您可能需要对它们进行 polyfill。
此外,还有一个特殊的 onUpdate,在每次对象获得新属性时调用,这对于像 self => (self.verticesNeedUpdate = true)
这样的事情非常有用。
还请注意画布元素上的 onPointerMissed,它会在点击未命中任何网格时触发。
Event data 事件对象数据
pointerenter
和 pointerleave
与 pointerover 和 pointerout在使用时时一样的效果. 但是pointerenter
and pointerleave
语义尚未实现(它们虽然使用效果相同,但是有一些内在的差异,使用时可能需要注意).
How does event-system works, bubbling and capture
事件系统如何工作?冒泡和捕获?
有些事件(例如pointerout
)会在eventObject
和射线之间没有交集时发生。当发生这种情况时,事件将包含来自先前事件与此对象的交集数据。
Event propagation(bubbling) 事件传播
因为在3D中,物体可以互相遮挡,所以事件传播(Propagation)的方式与DOM有些不同。事件的交集数组包含所有与射线相交的物体,而不仅仅是最近的物体。每个物体的第一个交点才会被包含在事件中。事件首先被传递到离相机最近的物体,然后像在DOM中一样从其祖先元素中冒泡。之后,它被传递到下一个最近的物体,然后是它的祖先元素,以此类推。这意味着,默认情况下,即使物体处理了事件,它们对指针事件也是透明的(这个透明指的是,后面的那些三维物体也能透过遮挡在前面的三维物体接受到事件)。
event.stopPropagation()
不仅会阻止事件冒泡,还会阻止事件被传递到更远的对象(该对象后面的对象)。当指针悬停在该对象上时,所有其他更近或更远的对象都不再被视为被点击。如果它们之前收到了pointerover
事件,则会立即收到pointerout
事件。
如果你想让一个对象阻止后面的对象接收指针事件,它需要有一个事件处理程序,即使你不想让该对象响应指针事件。如果你想同时处理该事件并使用stopPropagation()
,请记住,在调用stopPropagation()
期间,pointerout
事件也会发生。你可能希望在此之后进行其他事件处理。
Pointer capture 指针捕获
因为事件会传递给所有相交的对象,因此捕获指针的方式也有所不同。在DOM中,捕获对象替换了命中测试,但在React Three Fiber中,捕获对象被添加到命中测试结果中:如果未命中捕获对象,则所有命中对象(及其祖先)首先接收事件,然后是捕获对象及其祖先。捕获对象还可以使用event.stopPropagation(),以便真正被命中的对象得到pointerout事件。
请注意,您只能通过event.target访问setPointerCapture和releasePointerCapture方法:它们不会添加到场景数据中的Object3D实例中。
setPointerCapture和releasePointerCapture采用与DOM中相同的pointerId参数,但目前它们不支持多个活动指针。
Customizing the event setting 自定义事件设置
在一些高级的使用场景中我们需要自定义设置事件的一些设置,我们可以通过<Canvas /> 元素的events属性来进行全局的事件管理:
Using a different target element 使用不同的目标对象
有些情况下,你可能希望将事件处理程通过DOM元素来触发,而不是canvas。这通常是为了在共享的父元素上处理事件,这样可以让画布和DOM覆盖层都能够接收事件。
你可以使用event管理:
或者,canvas元素上有个eventSource属性可以设置dom姐弟哪和通过React.Ref指向的dom对象。
Using a different prefix(DOM only) 使用不同的前缀(只有DOM可以)
默认情况下Fiber会使用offsetX/offsetY作为前缀去设置raycaster。你可以通过eventPrefix属性来进行自定义设置。
Allow raycast without user interaction 用户无交互可以投射射线
默认情况下,Fiber只会在用户与画布交互时进行射线投射。如果这样的情况,比如相机将可悬停对象移动到光标下方,它将不会触发hover事件。如果需要这种行为,即在这样的情况你也想触发hover事件,您可以通过执行update()来强制进行射线投射,在需要时随时调用它。
你可以把这个行为抽象到更复杂的逻辑中