-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
66 changed files
with
3,079 additions
and
293 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import { unsafe__useFiveInstance } from '@realsee/five/react' | ||
import * as React from 'react' | ||
import { PlayController } from '../../resources/PlayController' | ||
import { VreoKeyframe, VreoKeyframeEnum, VreoUnit } from '../../resources/typings/VreoUnit' | ||
|
||
import './index.css' | ||
|
||
// 全局单例:可以放置在您的 Store/Controller 层里面。 | ||
const playController = new PlayController() | ||
|
||
Object.assign(window, { $playController: playController }) | ||
|
||
/** | ||
* 触发按钮 | ||
*/ | ||
function Button() { | ||
const [state, setState] = React.useState(false) | ||
|
||
React.useEffect(() => { | ||
const setPlaying = () => setState(true) | ||
const setPaused = () => setState(false) | ||
playController.on('playing', setPlaying) | ||
playController.on('paused', setPaused) | ||
|
||
return () => { | ||
playController.off('playing', setPlaying) | ||
playController.off('paused', setPaused) | ||
} | ||
}, []) | ||
|
||
return ( | ||
<button | ||
className="pure-button pure-button-primary PlayController-Button" | ||
onClick={async () => { | ||
if (!playController.paused) { | ||
await playController.pause() | ||
return | ||
} | ||
|
||
if (playController.vreoUnit) { | ||
await playController.play() | ||
return | ||
} | ||
|
||
// 构造讲房数据 | ||
const vreoUnit: VreoUnit = { | ||
categoryId: 'agent_navigation', | ||
categoryText: '经纪人讲房', | ||
frontRequestId: '10010', | ||
index: 0, | ||
video: { | ||
url: '//vrlab-public.ljcdn.com/release/vradmin/media/047b652f-bc01-487a-231e-2549595b5a85.mp3', | ||
start: 0, | ||
end: 130724, | ||
duration: 130724, | ||
}, | ||
keyframes: [] | ||
} | ||
// 请求讲房序列帧 | ||
const json = await fetch('//vrlab-public.ljcdn.com/release/vradmin/media/f8e6ebf8-ad0b-41e2-16b2-6ded49cda037.json') | ||
const tracks = (await json.json()).track | ||
|
||
const keyframes = tracks.map((track: Record<string, any>) => { | ||
const vreoKeyframe: VreoKeyframe = { | ||
uuid: '', | ||
// 由于是人为录制的,所以所有的序列帧都是 Custom 类型 | ||
type: VreoKeyframeEnum.Custom, | ||
start: track.currentTime, | ||
end: 0, | ||
data: Object.assign({ | ||
// 可以以字段内内容 识别是 经纪人讲房录制的数据 | ||
type: 'AgentNavigation', | ||
}, track) | ||
} | ||
return vreoKeyframe | ||
}) | ||
|
||
vreoUnit.keyframes = keyframes | ||
|
||
await playController.load(vreoUnit) | ||
await playController.play() | ||
// playController.play() | ||
// playController.pause() | ||
}} | ||
> | ||
{!state ? '播放' : '暂停'} | ||
</button> | ||
) | ||
} | ||
|
||
/** | ||
* 面板:进度条状态 | ||
*/ | ||
function Panel() { | ||
const [percentage, setPercentage] = React.useState(0) | ||
|
||
React.useEffect(() => { | ||
const interval = setInterval(() => { | ||
// duration 可能不精准,建议使用 数据下发的 音频时长 | ||
const duration = playController.duration | ||
const currentTime = playController.currentTime | ||
|
||
setPercentage(currentTime / duration * 100) | ||
}, 300) | ||
|
||
return () => { | ||
if (interval) { | ||
clearInterval(interval) | ||
} | ||
} | ||
}, []) | ||
|
||
return ( | ||
<div className="PlayController-Panel"> | ||
<div className="progress" style={{ width: percentage + '%' }}> | ||
{percentage.toFixed(2) + '%'} | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
/** | ||
* 您的解析逻辑,以 Five 为例 | ||
*/ | ||
export function YourHandler() { | ||
const five = unsafe__useFiveInstance() | ||
|
||
React.useEffect(() => { | ||
const hanlder = (vreoKeyframe: VreoKeyframe) => { | ||
// 不是自定义类型的剧本帧,不解析 | ||
if (vreoKeyframe.type !== VreoKeyframeEnum.Custom) { | ||
return | ||
} | ||
// 是自定义,但不是 经纪人讲房 录制,同样不解析 | ||
const data = vreoKeyframe.data | ||
if (data.type !== 'AgentNavigation') { | ||
return | ||
} | ||
|
||
// 解析各个字段,执行不同的渲染逻辑 | ||
// camera 相机 | ||
if (data.camera) { | ||
five.updateCamera({ | ||
fov: data.camera.fov, | ||
longitude: data.camera.longitude, | ||
latitude: data.camera.latitude, | ||
}, 0) | ||
} | ||
// position 点位 | ||
if (data.position && data.position.panoIndex && data.position.panoIndex !== five.panoIndex) { | ||
five.moveToPano(data.position.panoIndex) | ||
} | ||
} | ||
|
||
playController.on(VreoKeyframeEnum.Custom, hanlder) | ||
|
||
return () => { | ||
playController.off(VreoKeyframeEnum.Custom, hanlder) | ||
} | ||
}, []) | ||
|
||
return <></> | ||
} | ||
|
||
export function App() { | ||
return ( | ||
<div className="PlayController-App"> | ||
<Button /> | ||
<Panel /> | ||
<YourHandler /> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
.PlayController-Button { | ||
position: fixed; | ||
right: 24px; | ||
top: 24px; | ||
} | ||
|
||
.PlayController-Panel { | ||
position: fixed; | ||
height: 42px; | ||
width: 340px; | ||
background-color: #009688; | ||
bottom: 36px; | ||
left: 50%; | ||
transform: translate(-50%, 0); | ||
} | ||
|
||
.progress { | ||
position: absolute; | ||
left: 0; | ||
top: 0; | ||
background-color: brown; | ||
color: white; | ||
height: 100%; | ||
width: 0; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
overflow: hidden; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { FiveInitArgs, parseWork } from '@realsee/five' | ||
import { createFiveProvider } from '@realsee/five/react' | ||
import * as React from 'react' | ||
import ReactDOM from 'react-dom' | ||
import { ResponsiveFullScreenFiveCanvas } from '../components/ResponsiveFullScreenFiveCanvas' | ||
import work from './work.json' | ||
|
||
import '../index.css' | ||
import { App } from './App' | ||
|
||
const defaultInitArgs: FiveInitArgs = { | ||
imageOptions: { size: 1024 }, | ||
textureOptions: { size: 64 }, | ||
onlyRenderIfNeeds: true, | ||
antialias: false, | ||
model: {}, | ||
plugins: [], | ||
} | ||
|
||
const FiveProvider = createFiveProvider(defaultInitArgs) | ||
|
||
ReactDOM.render( | ||
<React.StrictMode> | ||
<FiveProvider initialWork={parseWork(work)} ref={(ref) => Object.assign(window, { $five: ref?.five })}> | ||
<ResponsiveFullScreenFiveCanvas /> | ||
<App /> | ||
</FiveProvider> | ||
</React.StrictMode>, | ||
document.getElementById('root') | ||
) |
Oops, something went wrong.