Как создать прослушиватель событий щелчка на react-three-fiber / three.js ?

#javascript #reactjs #three.js #react-three-fiber

#javascript #reactjs #three.js #реакция-трехволоконный

Вопрос:

Я пытаюсь прослушать события щелчка на моем реагирующем трехслойном холсте. Но я получаю другое событие при использовании addEventListener .

onClick свойство mesh возвращает следующее событие:

       <mesh position={[0, 0, 0]} onClick={(e) => console.log('onClick mesh: ', e)}>
        <boxGeometry attach="geometry" args={[10, 10, 10]} />
        <meshStandardMaterial attach="material" color="hotpink" wireframe />
      </mesh>
 
 onClick mesh:  
{dispatchConfig: Object, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: Object…} 
// This is the event I need!!
 

И добавление прослушивателя событий возвращает следующее событие:

 const ThreeEventListener = () => {
  const onClickDocument = (e) => {
    console.log('onClick document listener: ', e)
  }
  useEffect(() => {
    document.addEventListener('click', onClickDocument, false)
    return () => document.removeEventListener('click', onClickDocument)
  })
  return null
}
 
 onClick document listener:  
MouseEvent {isTrusted: true, screenX: 1508, screenY: 427, clientX: 348, clientY: 178…}
// This is a normal DOM event from React that I dont need
 

Демонстрация (щелкните поле, чтобы запустить события)

Комментарии:

1. У Three нет событий, они поступают из R3F, который отслеживает события общего указателя, затем передает радиопередачи и формирует события уровня объекта. Добавив прослушиватели событий в холст, вы снова получите обычные события указателя. Но почему вы это делаете, в react вы не должны касаться dom.

Ответ №1:

Я предполагаю, что то, что вы получили в первый раз, — это экземпляр SyntheticEvent , который React использует в качестве оболочки поверх собственных событий, в сочетании с некоторыми полезными для react-трехслойными полями — вот документ. В документе говорится, что есть собственное событие браузера и three.js полезные данные внутри их реализации события (это то, что вы получили).

Я предлагаю перенести то, что вам нужно, из собственного события в синтетическое:

 event.nativeEvent 
 

Ответ №2:

Вот близкое решение, использующее внешнюю библиотеку под названием three.interaction :

 import { Interaction } from 'three.interaction'

const ThreeEventListener = () => {

    useEffect(() => {
        // init three.interaction on mount
        const interaction = new Interaction(gl, scene, camera);
    }, [])

    const onClickScene = (event) => {
        console.log('onClick scene listener: ', e)
    }

    useEffect(() => {
        // attach callbacks to clicks thanks to three.interaction
        scene.on('click', onClickScene)
        return () => scene.on('click', () => {})
    })

    return null
}
 

Событие, созданное three.interaction, выглядит следующим образом:

 onClick scene listener:  InteractionEvent {stopped: false, target: Scene, currentTarget: Scene, type: "click", data: InteractionData, …}
 

Комментарии:

1. Как бы вы это использовали? Я понимаю, как это работает, но не знаю, куда его поместить