状态录制
本章你可以学习到
- 通过 State 记录用户操作。
- 通过 State 还原用户操作画面。
- 在 React 中管理定时器与事件清理。
React 示例:模式切换 + 环视
- JavaScript
- TypeScript
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 FiveRecord() {
const containerRef = useRef(null)
const fiveRef = useRef(null)
const [mode, setMode] = useState('Panorama')
const timerRef = useRef(null)
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()
const onState = (s) => setMode(s.mode)
window.addEventListener('resize', onResize, false)
five.on('stateChange', onState)
return () => {
window.clearInterval(timerRef.current)
window.removeEventListener('resize', onResize, false)
five.off('stateChange', onState)
five.dispose()
}
}, [])
const switchMode = (m) => fiveRef.current?.setState({ mode: m })
const startLookAround = () => {
window.clearInterval(timerRef.current)
timerRef.current = window.setInterval(() => {
const f = fiveRef.current
if (!f) return
f.setState({ longitude: f.state.longitude + Math.PI / 360 })
}, 16)
}
const stopLookAround = () => window.clearInterval(timerRef.current)
return (
<div style={{ width: '100vw', height: '100vh' }}>
<div ref={containerRef} style={{ width: '100%', height: '100%', overflow: 'hidden' }} />
<div style={{ position: 'fixed', bottom: 16, left: 0, right: 0, display: 'flex', justifyContent: 'center', gap: 8 }}>
<button className={mode==='Panorama'?'btn btn-primary':'btn btn-outline-primary'} onClick={()=>switchMode('Panorama')}>全景漫游</button>
<button className={mode==='Floorplan'?'btn btn-primary':'btn btn-outline-primary'} onClick={()=>switchMode('Floorplan')}>空间总览</button>
</div>
<div style={{ position: 'fixed', top: 16, right: 16, display: 'flex', gap: 8 }}>
<button className="btn btn-light" onClick={startLookAround}>开始环视</button>
<button className="btn btn-light" onClick={stopLookAround}>停止环视</button>
</div>
</div>
)
}
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 FiveRecord() {
const containerRef = useRef<HTMLDivElement | null>(null)
const fiveRef = useRef<Five | null>(null)
const [mode, setMode] = useState<Mode>('Panorama')
const timerRef = useRef<number | null>(null)
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()
const onState = (s: { mode: Mode }) => setMode(s.mode)
window.addEventListener('resize', onResize, false)
five.on('stateChange', onState)
return () => {
if (timerRef.current) window.clearInterval(timerRef.current)
window.removeEventListener('resize', onResize, false)
five.off('stateChange', onState)
five.dispose()
}
}, [])
const switchMode = (m: Mode) => fiveRef.current?.setState({ mode: m })
const startLookAround = () => {
if (timerRef.current) window.clearInterval(timerRef.current)
timerRef.current = window.setInterval(() => {
const f = fiveRef.current
if (!f) return
f.setState({ longitude: f.state.longitude + Math.PI / 360 })
}, 16) as unknown as number
}
const stopLookAround = () => {
if (timerRef.current) window.clearInterval(timerRef.current)
}
return (
<div style={{ width: '100vw', height: '100vh' }}>
<div ref={containerRef} style={{ width: '100%', height: '100%', overflow: 'hidden' }} />
<div style={{ position: 'fixed', bottom: 16, left: 0, right: 0, display: 'flex', justifyContent: 'center', gap: 8 }}>
<button className={mode==='Panorama'?'btn btn-primary':'btn btn-outline-primary'} onClick={()=>switchMode('Panorama')}>全景漫游</button>
<button className={mode==='Floorplan'?'btn btn-primary':'btn btn-outline-primary'} onClick={()=>switchMode('Floorplan')}>空间总览</button>
</div>
<div style={{ position: 'fixed', top: 16, right: 16, display: 'flex', gap: 8 }}>
<button className="btn btn-light" onClick={startLookAround}>开始环视</button>
<button className="btn btn-light" onClick={stopLookAround}>停止环视</button>
</div>
</div>
)
}