@realsee/vreo 0.1.6-alpha.5 → 0.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -16
- package/docs/assets/custom.css +4 -4
- package/docs/assets/search.js +1 -1
- package/docs/classes/Player.Controller.html +54 -0
- package/docs/classes/Player.Player-1.html +11 -11
- package/docs/classes/Player.VideoAgentMesh.html +142 -0
- package/docs/classes/Player.VideoAgentScene.html +1 -0
- package/docs/enums/Player.InfoPanelStyleEnum.html +1 -0
- package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
- package/docs/enums/Player.PanoEffectEnum.html +2 -2
- package/docs/enums/Player.PanoTagEnum.html +1 -1
- package/docs/enums/Player.VreoKeyframeEnum.html +14 -12
- package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
- package/docs/enums/fivePlugins.Rotation.html +1 -1
- package/docs/index.html +52 -19
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -0
- package/docs/interfaces/Player.PlayerConfigs.html +4 -2
- package/docs/interfaces/Player.Vertex.html +1 -1
- package/docs/interfaces/Player.VideoAgentMeshOptions.html +1 -0
- package/docs/interfaces/Player.VreoKeyframe.html +1 -1
- package/docs/interfaces/Player.VreoUnit.html +1 -1
- package/docs/interfaces/Player.VreoVideo.html +1 -1
- package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +1 -1
- package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +3 -3
- package/docs/interfaces/fivePlugins.CameraMovementPluginParameterType.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +1 -1
- package/docs/interfaces/react.VreoActionCallbacks.html +15 -7
- package/docs/interfaces/react.VreoProviderProps.html +1 -0
- package/docs/modules/Player.html +17 -15
- package/docs/modules/custom.html +3 -0
- package/docs/modules/fivePlugins.html +2 -2
- package/docs/modules/react.html +1 -1
- package/docs/modules.html +1 -1
- package/lib/PlayController/createHTMLAudioElement.d.ts +1 -0
- package/lib/PlayController/createHTMLAudioElement.js +47 -0
- package/lib/PlayController/index.d.ts +38 -0
- package/lib/PlayController/index.js +300 -0
- package/lib/Player/App.js +8 -3
- package/lib/Player/Controller.d.ts +2 -0
- package/lib/Player/Controller.js +14 -0
- package/lib/Player/custom/SpatialScenePanel/index.d.ts +22 -0
- package/lib/Player/custom/SpatialScenePanel/index.js +279 -0
- package/lib/Player/index.d.ts +1 -1
- package/lib/Player/index.js +98 -11
- package/lib/Player/modules/Drawer/index.js +1 -1
- package/lib/Player/modules/PopUp/index.d.ts +2 -0
- package/lib/Player/modules/PopUp/index.js +43 -0
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +1 -0
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +5 -1
- package/lib/Player/modules/VideoAgent/VideoAgentScene.d.ts +4 -1
- package/lib/Player/modules/VideoAgent/VideoAgentScene.js +2 -1
- package/lib/Player/modules/VideoAgent/index.d.ts +2 -0
- package/lib/Player/modules/VideoAgent/index.js +1 -1
- package/lib/Player/modules/keyframes/BgMusic/index.d.ts +2 -0
- package/lib/Player/modules/keyframes/BgMusic/index.js +76 -0
- package/lib/Player/modules/keyframes/CameraMovement/index.js +41 -5
- package/lib/Player/modules/keyframes/InfoPanel/index.js +105 -23
- package/lib/Player/modules/keyframes/ModelVideo/index.js +43 -6
- package/lib/Player/modules/keyframes/PanoTextLabel/index.js +4 -12
- package/lib/Player/modules/keyframes/Prompter/index.js +2 -15
- package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +68 -17
- package/lib/Player/typings.d.ts +19 -1
- package/lib/fivePlugins/CameraMovementPlugin/index.js +104 -90
- package/lib/fivePlugins/CameraMovementPlugin/typings.d.ts +1 -0
- package/lib/react/index.d.ts +10 -2
- package/lib/react/index.js +1 -1
- package/lib/shared-utils/createTransMatrix.d.ts +1 -0
- package/lib/shared-utils/createTransMatrix.js +43 -0
- package/lib/typings/VreoUnit.d.ts +47 -8
- package/lib/typings/VreoUnit.js +15 -6
- package/package.json +6 -6
- package/resources/PlayController/createHTMLAudioElement.ts +53 -0
- package/resources/PlayController/index.ts +167 -0
- package/resources/Player/App.tsx +6 -1
- package/resources/Player/Controller.ts +12 -0
- package/resources/Player/custom/SpatialScenePanel/index.tsx +264 -0
- package/resources/Player/index.tsx +56 -2
- package/resources/Player/modules/Drawer/index.tsx +1 -1
- package/resources/Player/modules/PopUp/index.tsx +26 -0
- package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +4 -3
- package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +2 -2
- package/resources/Player/modules/VideoAgent/index.tsx +3 -2
- package/resources/Player/modules/keyframes/BgMusic/index.tsx +66 -0
- package/resources/Player/modules/keyframes/CameraMovement/index.tsx +7 -3
- package/resources/Player/modules/keyframes/InfoPanel/index.tsx +109 -11
- package/resources/Player/modules/keyframes/ModelVideo/index.tsx +35 -2
- package/resources/Player/modules/keyframes/PanoTextLabel/index.tsx +2 -2
- package/resources/Player/modules/keyframes/Prompter/index.tsx +3 -14
- package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +72 -15
- package/resources/Player/typings.ts +21 -1
- package/resources/fivePlugins/CameraMovementPlugin/index.ts +59 -48
- package/resources/fivePlugins/CameraMovementPlugin/typings.ts +2 -1
- package/resources/react/index.tsx +12 -3
- package/resources/shared-utils/createTransMatrix.ts +12 -0
- package/resources/typings/VreoUnit.ts +56 -8
- package/stylesheets/custom/SpatialScenePanel.css +309 -0
- package/stylesheets/default.css +127 -9
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { BgMusicData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
3
|
+
import { useController } from '../../../hooks'
|
|
4
|
+
|
|
5
|
+
export function BgMusic() {
|
|
6
|
+
const controller = useController()
|
|
7
|
+
const timeoutIdRef = React.useRef<NodeJS.Timeout | null>(null)
|
|
8
|
+
const cleanTimeout = React.useCallback( () => {
|
|
9
|
+
if (timeoutIdRef.current) {
|
|
10
|
+
clearTimeout(timeoutIdRef.current)
|
|
11
|
+
timeoutIdRef.current = null
|
|
12
|
+
}
|
|
13
|
+
}, [])
|
|
14
|
+
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
const audio = new Audio()
|
|
17
|
+
audio.setAttribute('id', 'vreo-singleton-bgmusic')
|
|
18
|
+
audio.style.display = 'none'
|
|
19
|
+
|
|
20
|
+
audio.setAttribute('playsinline', 'true')
|
|
21
|
+
audio.loop = true
|
|
22
|
+
document.body.append(audio)
|
|
23
|
+
|
|
24
|
+
const callback = (keyframe: VreoKeyframe) => {
|
|
25
|
+
const { start, end } = keyframe
|
|
26
|
+
const { url } = keyframe.data as BgMusicData
|
|
27
|
+
audio.src = url
|
|
28
|
+
const playCallback = () => {
|
|
29
|
+
audio.play()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
audio.addEventListener('canplaythrough', playCallback)
|
|
33
|
+
|
|
34
|
+
cleanTimeout()
|
|
35
|
+
|
|
36
|
+
const cleanAudio = () => {
|
|
37
|
+
audio.pause()
|
|
38
|
+
audio.currentTime = 0
|
|
39
|
+
audio.src = ''
|
|
40
|
+
cleanTimeout()
|
|
41
|
+
audio.removeEventListener('canplaythrough', playCallback)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const duration = (end - start) || 5000
|
|
45
|
+
|
|
46
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
47
|
+
cleanAudio()
|
|
48
|
+
}, duration)
|
|
49
|
+
|
|
50
|
+
controller.once('paused', () => {
|
|
51
|
+
cleanAudio()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
controller.on(VreoKeyframeEnum.BgMusic, callback)
|
|
57
|
+
|
|
58
|
+
return () => {
|
|
59
|
+
controller.off(VreoKeyframeEnum.BgMusic, callback)
|
|
60
|
+
document.body.removeChild(audio)
|
|
61
|
+
cleanTimeout()
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return <></>
|
|
66
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { CameraMovementPlugin } from '../../../../fivePlugins/CameraMovementPlugin'
|
|
3
|
-
import { CameraMovementEffect, RotateArgs } from '../../../../fivePlugins/CameraMovementPlugin/typings'
|
|
3
|
+
import { CameraMovementEffect, MoveArgs, RotateArgs } from '../../../../fivePlugins/CameraMovementPlugin/typings'
|
|
4
4
|
import { CameraMovementData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
5
5
|
import { useController, useFiveInstance } from '../../../hooks'
|
|
6
6
|
|
|
@@ -18,9 +18,13 @@ export function CameraMovement() {
|
|
|
18
18
|
const cameraMovementData = data as CameraMovementData
|
|
19
19
|
const effect = cameraMovementData.effect
|
|
20
20
|
if (effect === CameraMovementEffect.Rotate) {
|
|
21
|
-
ref.current.rotate(data as RotateArgs, end - start)
|
|
21
|
+
await ref.current.rotate(data as RotateArgs, end - start)
|
|
22
|
+
} else if (effect === CameraMovementEffect.Move) {
|
|
23
|
+
await ref.current.move(data as MoveArgs, end - start)
|
|
24
|
+
} else if (cameraMovementData.panoIndex !== undefined && cameraMovementData.panoIndex !== five.panoIndex) {
|
|
25
|
+
await ref.current.move(data as MoveArgs, end - start)
|
|
22
26
|
} else {
|
|
23
|
-
ref.current.
|
|
27
|
+
await ref.current.rotate(data as RotateArgs, end - start)
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { ReactNode } from 'react'
|
|
3
|
+
import {
|
|
4
|
+
InfoPanelData,
|
|
5
|
+
InfoPanelStyleEnum,
|
|
6
|
+
InfoPanelTypeEnum,
|
|
7
|
+
VreoKeyframe,
|
|
8
|
+
VreoKeyframeEnum,
|
|
9
|
+
} from '../../../../typings/VreoUnit'
|
|
3
10
|
import { useController } from '../../../hooks'
|
|
4
11
|
|
|
5
|
-
function InfoPanelImg({ url }: { url: string }) {
|
|
12
|
+
function InfoPanelImg({ url, children }: { url: string; children?: ReactNode }) {
|
|
6
13
|
return (
|
|
7
14
|
<div className="vreo-infoPanel vreo-infoPanel--img">
|
|
8
|
-
|
|
15
|
+
{children}
|
|
16
|
+
<div className="vreo-infoPanelImg" style={{ backgroundImage: `url(${url})` }}></div>
|
|
9
17
|
</div>
|
|
10
18
|
)
|
|
11
19
|
}
|
|
12
20
|
|
|
13
|
-
function InfoPanelVideo({ url }: { url: string }) {
|
|
21
|
+
function InfoPanelVideo({ url, children }: { url: string; children?: ReactNode }) {
|
|
14
22
|
return (
|
|
15
23
|
<div className="vreo-infoPanel vreo-infoPanel--video">
|
|
16
|
-
|
|
24
|
+
{children}
|
|
25
|
+
<div className="vreo-infoPanelWrapper">
|
|
26
|
+
<video playsInline autoPlay className="vreo-infoPanelVideo" src={url} />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface TitleProps {
|
|
33
|
+
title?: string
|
|
34
|
+
subTitle?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const Title = (props: TitleProps) => {
|
|
38
|
+
if (!props.title && !props.subTitle) {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="vreo-infoPanel-title">
|
|
44
|
+
<div className="vreo-infoPanel-t1">{props.title}</div>
|
|
45
|
+
<div className="vreo-infoPanel-t2">{props.subTitle}</div>
|
|
17
46
|
</div>
|
|
18
47
|
)
|
|
19
48
|
}
|
|
@@ -26,20 +55,89 @@ export function InfoPanel() {
|
|
|
26
55
|
if (controller.configs?.keyframeMap.InfoPanel === false) {
|
|
27
56
|
return
|
|
28
57
|
}
|
|
58
|
+
|
|
29
59
|
const callback = (keyframe: VreoKeyframe) => {
|
|
30
60
|
const { start, end, data } = keyframe
|
|
31
61
|
|
|
32
62
|
const infoPanelData = data as InfoPanelData
|
|
33
63
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
64
|
+
const { title, subTitle, style } = infoPanelData
|
|
65
|
+
do {
|
|
66
|
+
if (style === InfoPanelStyleEnum.PopUp) {
|
|
67
|
+
if (infoPanelData.type === InfoPanelTypeEnum.Image) {
|
|
68
|
+
controller.openPopUp(
|
|
69
|
+
<InfoPanelImg url={infoPanelData.url}>
|
|
70
|
+
<Title title={title} subTitle={subTitle} />
|
|
71
|
+
</InfoPanelImg>
|
|
72
|
+
)
|
|
73
|
+
} else if (infoPanelData.type === InfoPanelTypeEnum.Video) {
|
|
74
|
+
controller.openPopUp(
|
|
75
|
+
<InfoPanelVideo url={infoPanelData.url}>
|
|
76
|
+
<Title title={title} subTitle={subTitle} />
|
|
77
|
+
</InfoPanelVideo>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
if (infoPanelData.type === InfoPanelTypeEnum.Image) {
|
|
83
|
+
controller.openDrawer({
|
|
84
|
+
content: (
|
|
85
|
+
<InfoPanelImg url={infoPanelData.url}>
|
|
86
|
+
<Title title={title} subTitle={subTitle} />
|
|
87
|
+
</InfoPanelImg>
|
|
88
|
+
),
|
|
89
|
+
height: '60vh',
|
|
90
|
+
})
|
|
91
|
+
} else if (infoPanelData.type === InfoPanelTypeEnum.Video) {
|
|
92
|
+
controller.openDrawer({
|
|
93
|
+
content: (
|
|
94
|
+
<InfoPanelVideo url={infoPanelData.url}>
|
|
95
|
+
<Title title={title} subTitle={subTitle} />
|
|
96
|
+
</InfoPanelVideo>
|
|
97
|
+
),
|
|
98
|
+
height: '60vh',
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
} while (false)
|
|
102
|
+
|
|
103
|
+
timeoutRef.current = setTimeout(() => {
|
|
104
|
+
controller.openDrawer(false)
|
|
105
|
+
controller.openPopUp(false)
|
|
106
|
+
}, end - start)
|
|
40
107
|
}
|
|
41
108
|
controller.on(VreoKeyframeEnum.InfoPanel, callback)
|
|
42
109
|
|
|
110
|
+
// Object.assign(window, {
|
|
111
|
+
// $setInfoPanel: () => {
|
|
112
|
+
// controller.openPopUp(
|
|
113
|
+
// // <InfoPanelImg url='//vrlab-static.ljcdn.com/release/web/psq/a.8e868cb2.gif' />
|
|
114
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/web/psq/b.f9a1ed52.png' />
|
|
115
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/web/psq/c.4f88c112.png' />
|
|
116
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/seesay/tools/cat_music___f68fb9bbe1f7cd6d00a16456dd0b09ad.gif' />
|
|
117
|
+
// <InfoPanelImg url="http://vrlab-public.ljcdn.com/common/images/web/d94e1bd7-0311-4b20-9c41-a1294fe43554.png">
|
|
118
|
+
// <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
119
|
+
// </InfoPanelImg>
|
|
120
|
+
// // <InfoPanelVideo url="//vrlab-public.ljcdn.com/release/seesay/tools/2022011713142___b320f74a5e1b5ad4bb46b4dc69d73ecc.mp4">
|
|
121
|
+
// // <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
122
|
+
// // </InfoPanelVideo>
|
|
123
|
+
// )
|
|
124
|
+
// },
|
|
125
|
+
// $setInfoPanel2: () => {
|
|
126
|
+
// controller.openPopUp(
|
|
127
|
+
// <InfoPanelImg url='//vrlab-static.ljcdn.com/release/web/psq/a.8e868cb2.gif' />
|
|
128
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/web/psq/b.f9a1ed52.png' />
|
|
129
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/web/psq/c.4f88c112.png' />
|
|
130
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/seesay/tools/cat_music___f68fb9bbe1f7cd6d00a16456dd0b09ad.gif' />
|
|
131
|
+
// // <InfoPanelImg url="http://vrlab-public.ljcdn.com/common/images/web/d94e1bd7-0311-4b20-9c41-a1294fe43554.png">
|
|
132
|
+
// // <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
133
|
+
// // </InfoPanelImg>
|
|
134
|
+
// // <InfoPanelVideo url="//vrlab-public.ljcdn.com/release/seesay/tools/2022011713142___b320f74a5e1b5ad4bb46b4dc69d73ecc.mp4">
|
|
135
|
+
// // <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
136
|
+
// // </InfoPanelVideo>
|
|
137
|
+
// )
|
|
138
|
+
// },
|
|
139
|
+
// })
|
|
140
|
+
|
|
43
141
|
return () => {
|
|
44
142
|
controller.off(VreoKeyframeEnum.InfoPanel, callback)
|
|
45
143
|
if (timeoutRef.current) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
+
import * as THREE from 'three'
|
|
2
3
|
import { ModelTVVideoPlugin } from '../../../../fivePlugins/ModelTVVideoPlugin'
|
|
4
|
+
import { createTransMatrix } from '../../../../shared-utils/createTransMatrix'
|
|
3
5
|
import { ModelVideoData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
4
6
|
import { useController, useFiveInstance } from '../../../hooks'
|
|
5
7
|
|
|
@@ -15,14 +17,45 @@ export function ModelVideo() {
|
|
|
15
17
|
ref.current = ModelTVVideoPlugin(five, {})
|
|
16
18
|
}
|
|
17
19
|
const { start, end } = keyframe
|
|
18
|
-
const { videoSrc, videoPosterSrc, vertexs } = keyframe.data as ModelVideoData
|
|
20
|
+
const { videoSrc, videoPosterSrc, vertexs, matrixWorld } = keyframe.data as ModelVideoData
|
|
21
|
+
|
|
22
|
+
const position = (() => {
|
|
23
|
+
if (vertexs.length < 4) {
|
|
24
|
+
throw new Error('ModelVideo: 顶点数据集合不够,无法组成矩形 ....')
|
|
25
|
+
}
|
|
26
|
+
if (vertexs.length === 4) {
|
|
27
|
+
return vertexs
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const box = new THREE.Box3()
|
|
31
|
+
vertexs.forEach((v) => box.expandByPoint(new THREE.Vector3(v.x, v.y, v.z)))
|
|
32
|
+
return [
|
|
33
|
+
new THREE.Vector3(box.min.x, box.max.y, box.max.z),
|
|
34
|
+
new THREE.Vector3(box.min.x, box.min.y, box.max.z),
|
|
35
|
+
new THREE.Vector3(box.max.x, box.min.y, box.max.z),
|
|
36
|
+
new THREE.Vector3(box.max.x, box.max.y, box.max.z),
|
|
37
|
+
]
|
|
38
|
+
})()
|
|
39
|
+
|
|
40
|
+
const points = (() => {
|
|
41
|
+
if (matrixWorld) {
|
|
42
|
+
const transMatrix = createTransMatrix(matrixWorld)
|
|
43
|
+
return [
|
|
44
|
+
position.map((p) => {
|
|
45
|
+
const res = transMatrix([p.x, p.y, p.z])
|
|
46
|
+
return { x: res[0], y: res[1], z: res[2] }
|
|
47
|
+
}),
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
return [position]
|
|
51
|
+
})()
|
|
19
52
|
|
|
20
53
|
ref.current.disable()
|
|
21
54
|
await ref.current.load(
|
|
22
55
|
{
|
|
23
56
|
video_src: videoSrc,
|
|
24
57
|
video_poster_src: videoPosterSrc,
|
|
25
|
-
points
|
|
58
|
+
points,
|
|
26
59
|
},
|
|
27
60
|
controller.configs?.videos?.modelTVVideo
|
|
28
61
|
)
|
|
@@ -30,13 +30,13 @@ export function PanoTextLabel() {
|
|
|
30
30
|
if (!res) return
|
|
31
31
|
const { x: left, y: top } = res
|
|
32
32
|
|
|
33
|
-
Object.assign(window, { $PanoTextLabel: { setState } })
|
|
33
|
+
// Object.assign(window, { $PanoTextLabel: { setState } })
|
|
34
34
|
setState({ left, top, text: data.text || '', fontSize: data.fontSize || 16 })
|
|
35
35
|
timeoutRef.current = setTimeout(() => setState(null), end - start)
|
|
36
36
|
}
|
|
37
37
|
controller.on(VreoKeyframeEnum.PanoTextLabel, callback)
|
|
38
38
|
|
|
39
|
-
Object.assign(window, { $panoTextLabel: { setState } })
|
|
39
|
+
// Object.assign(window, { $panoTextLabel: { setState } })
|
|
40
40
|
return () => {
|
|
41
41
|
controller.off(VreoKeyframeEnum.PanoTextLabel, callback)
|
|
42
42
|
if (timeoutRef.current) {
|
|
@@ -2,7 +2,6 @@ import * as React from 'react'
|
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import { useController } from '../../../hooks'
|
|
4
4
|
|
|
5
|
-
import { CSSTransition, TransitionGroup } from 'react-transition-group'
|
|
6
5
|
import { VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
7
6
|
|
|
8
7
|
export function Prompter() {
|
|
@@ -48,19 +47,9 @@ export function Prompter() {
|
|
|
48
47
|
'vreo-prompter--audio': controller.isAudio,
|
|
49
48
|
})}
|
|
50
49
|
>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<CSSTransition
|
|
55
|
-
key={text}
|
|
56
|
-
classNames="vreo-prompter-text-transition"
|
|
57
|
-
timeout={500}
|
|
58
|
-
addEndListener={(node, done) => node.addEventListener('transitionend', done, false)}
|
|
59
|
-
>
|
|
60
|
-
<div className="vreo-prompter-innerText">{text}</div>
|
|
61
|
-
</CSSTransition>
|
|
62
|
-
</TransitionGroup>
|
|
63
|
-
) : undefined}
|
|
50
|
+
<div className="vreo-prompter-text">
|
|
51
|
+
<div className="vreo-prompter-innerText">{text}</div>
|
|
52
|
+
</div>
|
|
64
53
|
</div>
|
|
65
54
|
)
|
|
66
55
|
}
|
|
@@ -1,42 +1,99 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import { parseWork,
|
|
2
|
+
import { parseWork, Work } from '@realsee/five'
|
|
3
3
|
import { useController, useFiveInstance } from '../../../hooks'
|
|
4
4
|
import { UpdateVRPanoramaData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
5
5
|
|
|
6
6
|
export function UpdateVRPanorama() {
|
|
7
7
|
const controller = useController()
|
|
8
8
|
const five = useFiveInstance()
|
|
9
|
+
const deafultWorkRef = React.useRef<string[] | null>(null)
|
|
10
|
+
const updateWorkRef = React.useRef<Work | null>(null)
|
|
11
|
+
|
|
12
|
+
// 恢复默认 VR
|
|
13
|
+
const restoreCallback = React.useCallback(() => {
|
|
14
|
+
// 先清理掉 之前的 VR 数据备份
|
|
15
|
+
updateWorkRef.current = null
|
|
16
|
+
|
|
17
|
+
if (deafultWorkRef.current) {
|
|
18
|
+
const work = parseWork(deafultWorkRef.current)
|
|
19
|
+
five.load(work)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}, [])
|
|
23
|
+
|
|
24
|
+
// 暂停时: 恢复默认 VR
|
|
25
|
+
const pausedCallback = React.useCallback(() => {
|
|
26
|
+
if (deafultWorkRef.current) {
|
|
27
|
+
const work = parseWork(deafultWorkRef.current)
|
|
28
|
+
Object.assign(window, {$rawWork: work})
|
|
29
|
+
five.load(work)
|
|
30
|
+
}
|
|
31
|
+
}, [])
|
|
32
|
+
|
|
33
|
+
// 播放时:如果暂停前有更新 VR 需要还原
|
|
34
|
+
const playingCallback = React.useCallback(() => {
|
|
35
|
+
if (!updateWorkRef.current) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
five.load(updateWorkRef.current)
|
|
39
|
+
}, [])
|
|
9
40
|
|
|
10
41
|
React.useEffect(() => {
|
|
11
42
|
const callback = (keyframe: VreoKeyframe) => {
|
|
12
|
-
|
|
43
|
+
if (!deafultWorkRef.current) {
|
|
44
|
+
deafultWorkRef.current = five.work.raw.works
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const data = keyframe.data as UpdateVRPanoramaData
|
|
13
48
|
|
|
14
|
-
|
|
15
|
-
|
|
49
|
+
// 如果数据中有新 work 数据,则直接载入
|
|
50
|
+
if (data.work) {
|
|
51
|
+
updateWorkRef.current = parseWork(data.work)
|
|
52
|
+
five.load(updateWorkRef.current)
|
|
16
53
|
return
|
|
17
54
|
}
|
|
18
55
|
|
|
19
|
-
|
|
20
|
-
|
|
56
|
+
const lastRawWork = five.work?.raw.works[0]
|
|
57
|
+
|
|
21
58
|
|
|
22
|
-
//
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
59
|
+
// 动态场景:不提供完成的签名数据,需重新整理
|
|
60
|
+
if (data.dynamic_scene && !data.panorama) {
|
|
61
|
+
const lastWork = JSON.parse(lastRawWork)
|
|
62
|
+
const panorama = lastWork.panorama
|
|
63
|
+
const index = data.dynamic_scene.images.index
|
|
64
|
+
panorama.list[index] = data.dynamic_scene.images
|
|
65
|
+
data.panorama = panorama
|
|
66
|
+
delete data.dynamic_scene
|
|
27
67
|
}
|
|
28
68
|
|
|
29
|
-
|
|
69
|
+
Object.assign(window, {$work1: JSON.parse(lastRawWork), $work2: data, parseWork: parseWork})
|
|
30
70
|
|
|
31
|
-
|
|
32
|
-
five.load(
|
|
71
|
+
updateWorkRef.current = parseWork([lastRawWork, data])
|
|
72
|
+
five.load(updateWorkRef.current)
|
|
33
73
|
}
|
|
34
74
|
|
|
35
75
|
controller.on(VreoKeyframeEnum.UpdateVRPanorama, callback)
|
|
76
|
+
|
|
77
|
+
// 离开 将之前的内容清空
|
|
78
|
+
controller.on(VreoKeyframeEnum.Exit, restoreCallback)
|
|
79
|
+
|
|
80
|
+
// 新载入数据 将之前的内容清空
|
|
81
|
+
controller.on('loaded', restoreCallback)
|
|
82
|
+
|
|
83
|
+
// 暂停 回到默认状态
|
|
84
|
+
controller.on('paused', pausedCallback)
|
|
85
|
+
// 播放 回归暂停前状态
|
|
86
|
+
controller.on('playing', playingCallback)
|
|
87
|
+
|
|
36
88
|
return () => {
|
|
89
|
+
// 清理事件监听
|
|
37
90
|
controller.off(VreoKeyframeEnum.UpdateVRPanorama, callback)
|
|
91
|
+
controller.off(VreoKeyframeEnum.Exit, restoreCallback)
|
|
92
|
+
controller.off('loaded', restoreCallback)
|
|
93
|
+
controller.off('paused', pausedCallback)
|
|
94
|
+
controller.off('playing', playingCallback)
|
|
38
95
|
}
|
|
39
|
-
}, [
|
|
96
|
+
}, [])
|
|
40
97
|
|
|
41
98
|
return <></>
|
|
42
99
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Subscribe, Five } from '@realsee/five';
|
|
3
|
+
|
|
4
|
+
import { VreoKeyframeConfigMap, VreoKeyframeEvent } from '../typings/VreoUnit'
|
|
5
|
+
import { VideoAgentMeshOptions } from './modules/VideoAgent/VideoAgentMesh';
|
|
2
6
|
|
|
3
7
|
export interface PlayerConfigs {
|
|
4
8
|
containter?: ReactDOM.Container
|
|
@@ -12,4 +16,20 @@ export interface PlayerConfigs {
|
|
|
12
16
|
videoEffect?: HTMLVideoElement
|
|
13
17
|
modelTVVideo?: HTMLVideoElement
|
|
14
18
|
}
|
|
19
|
+
|
|
20
|
+
videoAgentMeshOptions?: VideoAgentMeshOptions
|
|
21
|
+
/**
|
|
22
|
+
* 如果需要在 底部面板添加自定义内容,可以传递个 React 组件。
|
|
23
|
+
*/
|
|
24
|
+
customPanelChildren?: ReactNode
|
|
25
|
+
customKeyframes?: React.FC<CustomVreoKeyframeProps>[]
|
|
26
|
+
imageOptions?: { size: number }
|
|
27
|
+
autoPreload?: boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type VreoSubscribe = Pick<Subscribe<VreoKeyframeEvent>, 'on' | 'once' | 'off'>
|
|
31
|
+
|
|
32
|
+
export interface CustomVreoKeyframeProps {
|
|
33
|
+
subscribe: VreoSubscribe
|
|
34
|
+
five: Five
|
|
15
35
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Five } from '@realsee/five'
|
|
1
|
+
import { Five, MovePanoOptions } from '@realsee/five'
|
|
2
2
|
import type { FivePlugin } from '@realsee/five'
|
|
3
3
|
import * as TWEEN from '@tweenjs/tween.js'
|
|
4
4
|
|
|
@@ -50,63 +50,73 @@ function progressNumber(from: number, to: number, pst: number) {
|
|
|
50
50
|
export const CameraMovementPlugin: FivePlugin<CameraMovementPluginParameterType, CameraMovementPluginExportType> = (
|
|
51
51
|
five: Five,
|
|
52
52
|
) => {
|
|
53
|
-
const move =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const move = (args: Partial<MoveArgs>, duration: number, opts: MoveOpts = { preload: true }) => {
|
|
54
|
+
return new Promise<boolean>(async (resolve, reject) => {
|
|
55
|
+
|
|
56
|
+
if (opts.asyncStartCallback) {
|
|
57
|
+
opts.asyncStartCallback()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (five.panoIndex === undefined) {
|
|
61
|
+
return reject(false)
|
|
62
|
+
}
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
if (args.mode && args.mode !== five.currentMode) {
|
|
65
|
+
await new Promise((resolve) => {
|
|
66
|
+
if (!args.mode) return
|
|
67
|
+
five.once('modeChange', (mode) => {
|
|
68
|
+
five.once('initAnimationEnded', () => {
|
|
69
|
+
if (mode === args.mode) {
|
|
70
|
+
resolve(true)
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
five.changeMode(args.mode, {
|
|
75
|
+
fov: args.fov || undefined,
|
|
76
|
+
latitude: args.latitude || undefined,
|
|
77
|
+
longitude: args.longitude || undefined,
|
|
78
|
+
panoIndex: args.panoIndex || undefined,
|
|
66
79
|
})
|
|
67
80
|
})
|
|
68
|
-
|
|
69
|
-
fov: args.fov || undefined,
|
|
70
|
-
latitude: args.latitude || undefined,
|
|
71
|
-
longitude: args.longitude || undefined,
|
|
72
|
-
panoIndex: args.panoIndex || undefined,
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
}
|
|
81
|
+
}
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
if (args.mode === Five.Mode.Floorplan) {
|
|
84
|
+
return resolve(true)
|
|
85
|
+
}
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
if (opts.preload && args.panoIndex !== undefined && args.panoIndex !== five.panoIndex) {
|
|
88
|
+
await five.preloadPano(args.panoIndex)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (opts.asyncEndCallback) {
|
|
92
|
+
opts.asyncEndCallback()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
args.panoIndex === undefined &&
|
|
97
|
+
args.fov === undefined &&
|
|
98
|
+
args.latitude === undefined &&
|
|
99
|
+
args.longitude === undefined
|
|
100
|
+
) {
|
|
101
|
+
return resolve(true)
|
|
102
|
+
}
|
|
84
103
|
|
|
85
|
-
if (opts.asyncEndCallback) {
|
|
86
|
-
opts.asyncEndCallback()
|
|
87
|
-
}
|
|
88
104
|
|
|
89
|
-
if (
|
|
90
|
-
args.panoIndex === undefined &&
|
|
91
|
-
args.fov === undefined &&
|
|
92
|
-
args.latitude === undefined &&
|
|
93
|
-
args.longitude === undefined
|
|
94
|
-
) {
|
|
95
|
-
return true
|
|
96
|
-
}
|
|
97
|
-
return await new Promise<boolean>((resolve, reject) => {
|
|
98
105
|
const panoIndex = args.panoIndex !== undefined ? args.panoIndex : five.panoIndex
|
|
106
|
+
|
|
99
107
|
if (panoIndex !== undefined) {
|
|
100
|
-
|
|
108
|
+
const movePanoOptions: MovePanoOptions = Object.assign(args, {
|
|
109
|
+
duration, // 移动耗时
|
|
110
|
+
moveEndCallback: () => resolve(true), // 移动结束
|
|
111
|
+
moveCancelCallback: () => {
|
|
112
|
+
resolve(true)
|
|
113
|
+
}, // 移动开始
|
|
114
|
+
// effect: args.transEffect || 'fade',
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await five.moveToPano(
|
|
101
118
|
panoIndex,
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
duration, // 移动耗时
|
|
105
|
-
moveEndCallback: () => resolve(true), // 移动结束
|
|
106
|
-
moveCancelCallback: () => reject(false), // 移动开始
|
|
107
|
-
},
|
|
108
|
-
args,
|
|
109
|
-
),
|
|
119
|
+
movePanoOptions,
|
|
110
120
|
)
|
|
111
121
|
} else {
|
|
112
122
|
reject(false)
|
|
@@ -154,6 +164,7 @@ export const CameraMovementPlugin: FivePlugin<CameraMovementPluginParameterType,
|
|
|
154
164
|
five.moveToPano(args.panoIndex, {
|
|
155
165
|
moveEndCallback: () => resolve(true), // 移动结束
|
|
156
166
|
moveCancelCallback: () => reject(false), // 移动开始
|
|
167
|
+
effect: 'fade',
|
|
157
168
|
})
|
|
158
169
|
})
|
|
159
170
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable prettier/prettier */
|
|
2
|
-
import { Mode, Pose } from '@realsee/five'
|
|
2
|
+
import { Mode, MovePanoOptions, Pose } from '@realsee/five'
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
5
5
|
export interface CameraMovementPluginParameterType { }
|
|
@@ -39,6 +39,7 @@ export interface CameraMovementOptsCallback {
|
|
|
39
39
|
export type MoveArgs = {
|
|
40
40
|
mode: Mode
|
|
41
41
|
panoIndex: number
|
|
42
|
+
transEffect?: "fly" | "fade" | "instant"
|
|
42
43
|
} & Pose
|
|
43
44
|
|
|
44
45
|
export type MoveOpts = {
|