In this chapter you will learn
- How to use the Five SDK event system (
tapGesture, etc.) in React. - How to obtain 3D coordinates from
tapGestureand project them to screen coordinates.
Event system overview
tapGesture: click/touch. The default behavior is moving to a point.panGesture: drag to rotate/pan.pinchGesture: two-finger zoom.mouseWheel: scroll-wheel zoom.- You can prevent the default behavior by listening for a
wants*event and returningfalsefrom the callback, for examplewantsTapGesture.
React example: pick a 3D point on click
import { useEffect, useRef, useState } from 'react'
import { Five, Mode, parseWork } from '@realsee/five'
const workURL = 'https://vr-public.realsee-cdn.cn/release/static/image/release/five/work-sample/07bdc58f413bc5494f05c7cbb5cbdce4/work.json'
export default function FivePoints() {
const containerRef = useRef(null)
const fiveRef = useRef(null)
const [enabled, setEnabled] = useState(false)
const [points, setPoints] = useState([])
useEffect(() => {
const five = new Five()
fiveRef.current = five
if (containerRef.current) five.appendTo(containerRef.current)
fetch(workURL).then(r=>r.json()).then(json=>five.load(parseWork(json)))
const onResize = () => five.refresh()
window.addEventListener('resize', onResize, false)
const onWantsTap = (raycaster) => {
if (!enabled) return true
const intersection = five.model.intersectRaycaster(raycaster)
if (intersection) {
setPoints((prev) => [...prev, ...intersection])
}
return false
}
five.on('wantsTapGesture', onWantsTap)
return () => {
window.removeEventListener('resize', onResize, false)
five.off('wantsTapGesture', onWantsTap)
five.dispose()
}
}, [enabled])
return (
<div style={{ width: '100vw', height: '100vh' }}>
<div ref={containerRef} style={{ width: '100%', height: '100%', overflow: 'hidden' }} />
<div style={{ position: 'fixed', top: 16, left: 16, display: 'flex', gap: 8 }}>
<button className="btn btn-primary" onClick={()=>setEnabled(v=>!v)}>{enabled? 'Disable picking':'Enable picking'}</button>
</div>
<div style={{ position: 'fixed', bottom: 16, left: 16, background: '#fff', padding: 8, borderRadius: 4, maxWidth: 320 }}>
<div>Picked: {points.length}</div>
</div>
</div>
)
}import { useEffect, useMemo, useRef, useState } from 'react'
import { Five, parseWork } from '@realsee/five'
import type { Vector3 } from 'three'
const workURL = 'https://vr-public.realsee-cdn.cn/release/static/image/release/five/work-sample/07bdc58f413bc5494f05c7cbb5cbdce4/work.json'
export default function FivePoints() {
const containerRef = useRef<HTMLDivElement | null>(null)
const fiveRef = useRef<Five | null>(null)
const [enabled, setEnabled] = useState(false)
const [points, setPoints] = useState<Vector3[]>([])
useEffect(() => {
const five = new Five()
fiveRef.current = five
if (containerRef.current) five.appendTo(containerRef.current)
fetch(workURL).then(r=>r.json()).then(json=>five.load(parseWork(json)))
const onResize = () => five.refresh()
window.addEventListener('resize', onResize, false)
const onWantsTap = (raycaster: any) => {
if (!enabled) return true
const intersection = five.model.intersectRaycaster(raycaster)
if (intersection) setPoints((prev) => [...prev, ...intersection])
return false
}
five.on('wantsTapGesture', onWantsTap)
return () => {
window.removeEventListener('resize', onResize, false)
five.off('wantsTapGesture', onWantsTap)
five.dispose()
}
}, [enabled])
return (
<div style={{ width: '100vw', height: '100vh' }}>
<div ref={containerRef} style={{ width: '100%', height: '100%', overflow: 'hidden' }} />
<div style={{ position: 'fixed', top: 16, left: 16, display: 'flex', gap: 8 }}>
<button className="btn btn-primary" onClick={()=>setEnabled(v=>!v)}>{enabled? 'Disable picking':'Enable picking'}</button>
</div>
<div style={{ position: 'fixed', bottom: 16, left: 16, background: '#fff', padding: 8, borderRadius: 4, maxWidth: 320 }}>
<div>Picked: {points.length}</div>
</div>
</div>
)
}To map a 3D point to screen coordinates, use five.project2d(vector, testModel); see the next chapter, "Adding Tags".
