@realsee/vreo 0.2.0-alpha.1 → 0.2.0-alpha.12

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.
Files changed (97) hide show
  1. package/README.md +104 -17
  2. package/docs/assets/custom.css +4 -4
  3. package/docs/assets/search.js +1 -1
  4. package/docs/classes/Player.Controller.html +54 -0
  5. package/docs/classes/Player.Player-1.html +9 -9
  6. package/docs/classes/Player.VideoAgentMesh.html +142 -0
  7. package/docs/classes/Player.VideoAgentScene.html +1 -0
  8. package/docs/enums/Player.InfoPanelStyleEnum.html +1 -0
  9. package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
  10. package/docs/enums/Player.PanoEffectEnum.html +2 -2
  11. package/docs/enums/Player.PanoTagEnum.html +1 -1
  12. package/docs/enums/Player.PanoTagStyleEnum.html +7 -0
  13. package/docs/enums/Player.VreoKeyframeEnum.html +13 -13
  14. package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
  15. package/docs/enums/fivePlugins.Rotation.html +1 -1
  16. package/docs/index.html +53 -20
  17. package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -0
  18. package/docs/interfaces/Player.PlayerConfigs.html +3 -3
  19. package/docs/interfaces/Player.Vertex.html +1 -1
  20. package/docs/interfaces/Player.VideoAgentMeshOptions.html +1 -0
  21. package/docs/interfaces/Player.VreoKeyframe.html +1 -1
  22. package/docs/interfaces/Player.VreoUnit.html +1 -1
  23. package/docs/interfaces/Player.VreoVideo.html +1 -1
  24. package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +1 -1
  25. package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +3 -3
  26. package/docs/interfaces/fivePlugins.CameraMovementPluginParameterType.html +1 -1
  27. package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +1 -1
  28. package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +1 -1
  29. package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +1 -1
  30. package/docs/interfaces/react.VreoActionCallbacks.html +15 -7
  31. package/docs/interfaces/react.VreoProviderProps.html +1 -0
  32. package/docs/modules/Player.html +17 -15
  33. package/docs/modules/custom.html +3 -0
  34. package/docs/modules/fivePlugins.html +2 -2
  35. package/docs/modules/react.html +1 -1
  36. package/docs/modules.html +1 -1
  37. package/lib/PlayController/createHTMLAudioElement.d.ts +1 -0
  38. package/lib/PlayController/createHTMLAudioElement.js +47 -0
  39. package/lib/PlayController/index.d.ts +38 -0
  40. package/lib/PlayController/index.js +300 -0
  41. package/lib/Player/App.js +4 -3
  42. package/lib/Player/Controller.d.ts +2 -0
  43. package/lib/Player/Controller.js +14 -0
  44. package/lib/Player/custom/SpatialScenePanel/index.d.ts +22 -0
  45. package/lib/Player/custom/SpatialScenePanel/index.js +279 -0
  46. package/lib/Player/index.d.ts +2 -2
  47. package/lib/Player/index.js +102 -12
  48. package/lib/Player/modules/PopUp/index.d.ts +2 -0
  49. package/lib/Player/modules/PopUp/index.js +43 -0
  50. package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +2 -1
  51. package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +26 -20
  52. package/lib/Player/modules/VideoAgent/VideoAgentScene.d.ts +4 -1
  53. package/lib/Player/modules/VideoAgent/VideoAgentScene.js +2 -1
  54. package/lib/Player/modules/VideoAgent/index.d.ts +2 -0
  55. package/lib/Player/modules/VideoAgent/index.js +1 -1
  56. package/lib/Player/modules/keyframes/CameraMovement/index.js +41 -5
  57. package/lib/Player/modules/keyframes/InfoPanel/index.js +84 -36
  58. package/lib/Player/modules/keyframes/ModelVideo/index.js +45 -8
  59. package/lib/Player/modules/keyframes/PanoTag/index.js +19 -6
  60. package/lib/Player/modules/keyframes/PanoTextLabel/index.js +4 -12
  61. package/lib/Player/modules/keyframes/Prompter/index.js +4 -18
  62. package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +30 -18
  63. package/lib/Player/typings.d.ts +15 -2
  64. package/lib/fivePlugins/CameraMovementPlugin/index.js +104 -90
  65. package/lib/fivePlugins/CameraMovementPlugin/typings.d.ts +1 -0
  66. package/lib/react/index.d.ts +12 -4
  67. package/lib/react/index.js +3 -3
  68. package/lib/shared-utils/createTransMatrix.d.ts +1 -0
  69. package/lib/shared-utils/createTransMatrix.js +43 -0
  70. package/lib/typings/VreoUnit.d.ts +32 -6
  71. package/lib/typings/VreoUnit.js +26 -6
  72. package/package.json +6 -6
  73. package/resources/PlayController/createHTMLAudioElement.ts +53 -0
  74. package/resources/PlayController/index.ts +167 -0
  75. package/resources/Player/App.tsx +3 -1
  76. package/resources/Player/Controller.ts +12 -0
  77. package/resources/Player/custom/SpatialScenePanel/index.tsx +264 -0
  78. package/resources/Player/index.tsx +59 -4
  79. package/resources/Player/modules/PopUp/index.tsx +26 -0
  80. package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +7 -6
  81. package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +2 -2
  82. package/resources/Player/modules/VideoAgent/index.tsx +3 -2
  83. package/resources/Player/modules/keyframes/CameraMovement/index.tsx +7 -3
  84. package/resources/Player/modules/keyframes/InfoPanel/index.tsx +90 -23
  85. package/resources/Player/modules/keyframes/ModelVideo/index.tsx +36 -3
  86. package/resources/Player/modules/keyframes/PanoTag/index.tsx +31 -12
  87. package/resources/Player/modules/keyframes/PanoTextLabel/index.tsx +2 -2
  88. package/resources/Player/modules/keyframes/Prompter/index.tsx +5 -15
  89. package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +25 -16
  90. package/resources/Player/typings.ts +17 -2
  91. package/resources/fivePlugins/CameraMovementPlugin/index.ts +59 -48
  92. package/resources/fivePlugins/CameraMovementPlugin/typings.ts +2 -1
  93. package/resources/react/index.tsx +14 -5
  94. package/resources/shared-utils/createTransMatrix.ts +12 -0
  95. package/resources/typings/VreoUnit.ts +42 -7
  96. package/stylesheets/custom/SpatialScenePanel.css +309 -0
  97. package/stylesheets/default.css +116 -10
@@ -0,0 +1,264 @@
1
+ import * as React from 'react'
2
+ import ReactDOM from 'react-dom'
3
+ import { Five } from '@realsee/five'
4
+ import * as THREE from 'three'
5
+ import { Object3D, Raycaster, Vector3 } from 'three'
6
+ import { tweenProgress } from '@realsee/dnalogel/shared-utils/animationFrame/BetterTween'
7
+ import { CSS3DRenderPlugin, CSS3DRenderPluginExportType } from '@realsee/dnalogel/plugins/CSS3DRenderPlugin'
8
+
9
+ import { VreoKeyframe, VreoKeyframeEnum } from '../../../typings/VreoUnit'
10
+ import { CustomVreoKeyframeProps } from '../../typings'
11
+
12
+ // __debug__
13
+ // const mockData: SpatialScenePanelData = {
14
+ // customType: 'SpatialScenePanel',
15
+ // "stateList": [
16
+ // {
17
+ // "icon": "http://vrlab-public.ljcdn.com/release/seesay/tools/___fc42f951076607a22fd5c54f005ba553.png",
18
+ // "text": "窗帘关闭"
19
+ // },
20
+ // {
21
+ // "icon": "http://vrlab-public.ljcdn.com/release/seesay/tools/___b331e7ad732debc07250a169a3393b13.png",
22
+ // "text": "摄像头休眠"
23
+ // },
24
+ // {
25
+ // "icon": "http://vrlab-public.ljcdn.com/release/seesay/tools/___2e425a81ac0ad88232d50d4e52a9abfa.png",
26
+ // "text": "氛围音乐"
27
+ // },
28
+ // {
29
+ // "icon": "http://vrlab-public.ljcdn.com/release/seesay/tools/___bff48bb81cde37aa6a319d6f5d56e3a4.png",
30
+ // "text": "空调打开"
31
+ // }
32
+ // ],
33
+ // "temperature": "27",
34
+ // "title": "沉浸式回家"
35
+ // }
36
+ export interface SpatialScenePanelData {
37
+ customType: 'SpatialScenePanel'
38
+ title: string
39
+ temperature: string
40
+ stateList: {
41
+ text: string
42
+ icon: string
43
+ }[]
44
+ position?: { x: number; y: number; z: number }
45
+ quaternion?: [number, number, number, number]
46
+ }
47
+
48
+ interface SearchParams {
49
+ five: Five
50
+ // position: Vector3
51
+ // rotation?: Vector3
52
+ // quaternion: [number, number, number, number]
53
+ dom: HTMLDivElement
54
+ }
55
+
56
+ // const getSphere = (position: Vector3, color = 0xffff00) => {
57
+ // const geometry = new SphereGeometry(0.05, 32, 16)
58
+ // const material = new MeshBasicMaterial({ color })
59
+ // const sphere = new Mesh(geometry, material)
60
+ // sphere.position.copy(position)
61
+ // return sphere
62
+ // }
63
+
64
+ const searchV1 = ({ five, dom }: SearchParams) => {
65
+ const cameraDirection = new Vector3()
66
+ five.camera.getWorldDirection(cameraDirection)
67
+ const cameraPosition = five.camera.position
68
+ const [intersect] = five.model.intersectRaycaster(new Raycaster(cameraPosition, cameraDirection))
69
+ const point = five.project2d(intersect.point)
70
+
71
+ const widescreen = window.innerWidth > 560 ? true : false
72
+ // const width = dom!.clientWidth
73
+ const height = dom!.clientHeight
74
+ dom!.style.left = point!.x + 'px'
75
+ dom!.style.top = point!.y - height / 2 + 'px'
76
+ const rect = dom!.getBoundingClientRect()
77
+ const { left, top, bottom, right } = rect
78
+
79
+ const leftBottom = new Vector3(left, bottom)
80
+ const leftTop = new Vector3(left, top)
81
+ const rightTop = new Vector3(right, top)
82
+ const rightBottom = new Vector3(right, bottom)
83
+
84
+ const points = [leftBottom, rightBottom, rightTop, leftTop].map((point) => {
85
+ point.setX((point.x / window.innerWidth) * 2 - (widescreen ? 1.25: 1.75))
86
+ point.setY(-(point.y / window.innerHeight) * 2 + (widescreen ? 1.35: 1.125))
87
+ point.setZ(0.5)
88
+ return point.unproject(five.camera).addScaledVector(cameraDirection, 0.2)
89
+ })
90
+
91
+ // __debug__
92
+ // const colors = [0xdc143c, 0xffff00, 0x0000ff, 0x008000]
93
+ // points.forEach((p, index) => five.scene.add(getSphere(p, colors[index])))
94
+
95
+ // 判断是手机 150
96
+ const ratio = leftBottom.distanceTo(rightBottom) / (widescreen ? 150 : 120)
97
+ return { points, ratio }
98
+ }
99
+
100
+ /**
101
+ * 空间场景面板
102
+ * @returns
103
+ */
104
+ export function SpatialScenePanel(props: CustomVreoKeyframeProps) {
105
+ const timeoutRef = React.useRef<NodeJS.Timeout | null>(null)
106
+ const ref = React.useRef<HTMLDivElement>(null)
107
+ const panelRef = React.useRef<HTMLDivElement | null>(null)
108
+ const rendererRef = React.useRef<CSS3DRenderPluginExportType>(CSS3DRenderPlugin(props.five))
109
+
110
+ React.useEffect(() => {
111
+ if (!ref.current) {
112
+ return
113
+ }
114
+
115
+ const callback = (keyframe: VreoKeyframe) => {
116
+ if (keyframe.data.customType !== 'SpatialScenePanel') {
117
+ return
118
+ }
119
+
120
+ const data = keyframe.data as SpatialScenePanelData
121
+
122
+ // const data = mockData
123
+ const { points, ratio } = searchV1({
124
+ five: props.five,
125
+ dom: ref.current!,
126
+ })
127
+
128
+ const { container, dispose, css3DObject, render } =
129
+ rendererRef.current.create3DDomContainer(points, { ratio, autoRender: false }) || {}
130
+
131
+ Object.assign(window, { $css3DObject: css3DObject })
132
+ if (!container) return
133
+
134
+ ReactDOM.render(<Panel ref={(ref) => (panelRef.current = ref)} data={data} />, container)
135
+ const startRotateY = -(Math.PI * 2) / 9
136
+ let lastRotateY = 0
137
+
138
+ tweenProgress(1000)
139
+ .onUpdate(({ progress }) => {
140
+ const needRotateY = (Math.PI / 90) * 11 * progress
141
+ const rotateY = needRotateY - lastRotateY
142
+ css3DObject?.rotateY(rotateY)
143
+ // css3DObject?.rotateZ
144
+ lastRotateY = needRotateY
145
+ })
146
+ .onStart(() => {
147
+ css3DObject?.rotateY(startRotateY)
148
+ render!()
149
+ })
150
+ .onDispose(() => {
151
+ panelRef.current?.classList.add('show')
152
+ })
153
+ .play()
154
+
155
+ // Object.assign(window, { $dispose: () => {
156
+ // panelRef.current?.classList.add('hide')
157
+ // setTimeout(() => dispose?.(), 1500)
158
+ // } })
159
+
160
+ const { start, end } = keyframe
161
+
162
+ timeoutRef.current = setTimeout(() => {
163
+ panelRef.current?.classList.add('hide')
164
+ timeoutRef.current = setTimeout(() => {
165
+ dispose?.()
166
+ timeoutRef.current = null
167
+ }, 1500)
168
+ }, end - start)
169
+ }
170
+
171
+ Object.assign(window, { $callback: callback })
172
+
173
+ // setTimeout(() => {callback()}, 8000)
174
+ props.subscribe.on(VreoKeyframeEnum.Custom, callback)
175
+
176
+ return () => {
177
+ props.subscribe.off(VreoKeyframeEnum.Custom, callback)
178
+ if (timeoutRef.current) {
179
+ clearTimeout(timeoutRef.current)
180
+ }
181
+ }
182
+ }, [])
183
+
184
+ return <div className="vreo-SpatialScenePanel" ref={ref}></div>
185
+ }
186
+
187
+ /** 背景动画:控制延迟 */
188
+ function SpatialScenePanelBg() {
189
+ const ref = React.useRef<HTMLDivElement>(null)
190
+ const timeoutRef = React.useRef<NodeJS.Timeout | null>(null)
191
+ React.useEffect(() => {
192
+ if (!ref.current) return
193
+
194
+ const listener = () => {
195
+ ref.current?.setAttribute('class', 'SpatialScenePanel-bg')
196
+
197
+ timeoutRef.current = setTimeout(() => {
198
+ ref.current?.setAttribute('class', 'SpatialScenePanel-bg SpatialScenePanel-bg--animation')
199
+ timeoutRef.current = null
200
+ }, 3000)
201
+ }
202
+
203
+ ref.current.addEventListener('animationend', listener)
204
+
205
+ return () => {
206
+ if (ref.current) ref.current.removeEventListener('animationend', listener)
207
+ if (timeoutRef.current) clearTimeout(timeoutRef.current)
208
+ }
209
+ }, [])
210
+ return <div ref={ref} className="SpatialScenePanel-bg SpatialScenePanel-bg--animation"></div>
211
+ }
212
+
213
+ const Panel = React.forwardRef(
214
+ (props: { data: SpatialScenePanelData }, myRef: React.LegacyRef<HTMLDivElement> | undefined) => (
215
+ <div className="SpatialScenePanel" ref={myRef}>
216
+ <div className="SpatialScenePanel-show-area">
217
+ <SpatialScenePanelBg />
218
+ <div className="SpatialScenePanel-header">
219
+ <div className="SpatialScenePanel-title">{props.data?.title}</div>
220
+ <div className="SpatialScenePanel-temperature">{props.data?.temperature}℃</div>
221
+ </div>
222
+ <div className="SpatialScenePanel-body">
223
+ {props.data?.stateList?.map((state, index) => (
224
+ <div key={`scene-${state.text}`} className={`SpatialScenePanel-item index_${index}`}>
225
+ <img className="SpatialScenePanel-icon" src={state.icon}></img>
226
+ <div className="SpatialScenePanel-text">{state.text}</div>
227
+ <div className="SpatialScenePanel-dot"></div>
228
+ </div>
229
+ ))}
230
+ </div>
231
+ </div>
232
+
233
+ <div className="SpatialScenePanel-disappear-area"></div>
234
+ </div>
235
+ )
236
+ )
237
+
238
+
239
+ // export function SpatialScenePanel() {
240
+ // // const data = mockData
241
+
242
+ // return (
243
+ // <div className="SpatialScenePanel" >
244
+ // <div className="SpatialScenePanel-show-area">
245
+ // <SpatialScenePanelBg />
246
+ // <div className="SpatialScenePanel-header">
247
+ // <div className="SpatialScenePanel-title">{data?.title}</div>
248
+ // <div className="SpatialScenePanel-temperature">{data?.temperature}℃</div>
249
+ // </div>
250
+ // <div className="SpatialScenePanel-body">
251
+ // {data?.stateList?.map((state, index) => (
252
+ // <div key={`scene-${state.text}`} className={`SpatialScenePanel-item index_${index}`}>
253
+ // <img className="SpatialScenePanel-icon" src={state.icon}></img>
254
+ // <div className="SpatialScenePanel-text">{state.text}</div>
255
+ // <div className="SpatialScenePanel-dot"></div>
256
+ // </div>
257
+ // ))}
258
+ // </div>
259
+ // </div>
260
+
261
+ // <div className="SpatialScenePanel-disappear-area"></div>
262
+ // </div>
263
+ // )
264
+ // }
@@ -4,10 +4,11 @@ import { Five, Subscribe } from '@realsee/five'
4
4
 
5
5
  import { App } from './App'
6
6
  import { Controller, ControllerContext } from './Controller'
7
- import { VreoKeyframeEvent, VreoKeyframeConfigMap, VreoUnit } from '../typings/VreoUnit'
7
+ import { CameraMovementData, VreoKeyframeEnum, VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
8
8
  import { reaction } from 'mobx'
9
9
  import { Drawer } from './modules/Drawer'
10
10
  import { PlayerConfigs } from './typings'
11
+ import { PopUp } from './modules/PopUp'
11
12
 
12
13
  export class Player extends Subscribe<VreoKeyframeEvent> {
13
14
  $five: Five
@@ -42,6 +43,19 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
42
43
  <ControllerContext.Provider value={this.controller}>
43
44
  <App></App>
44
45
  <Drawer />
46
+ <PopUp />
47
+ {this.configs.customKeyframes &&
48
+ this.configs.customKeyframes.map((CustomCmpt, key) => (
49
+ <CustomCmpt
50
+ key={key}
51
+ subscribe={{
52
+ on: (name, callback) => this.on(name, callback),
53
+ once: (name, callback) => this.once(name, callback),
54
+ off: (name, callback) => this.off(name, callback),
55
+ }}
56
+ five={five}
57
+ />
58
+ ))}
45
59
  </ControllerContext.Provider>,
46
60
  configs.containter
47
61
  )
@@ -55,7 +69,10 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
55
69
  )
56
70
  }
57
71
 
58
- async load(vreoUnit: VreoUnit, currentTime = 0) {
72
+ async load(vreoUnit: VreoUnit, currentTime = 0, preload = false, force = false) {
73
+ if (force) {
74
+ vreoUnit = JSON.parse(JSON.stringify(vreoUnit))
75
+ }
59
76
  if (!this.controller.visible) {
60
77
  this.controller.setVisible(true)
61
78
  // 延迟 500ms 规避跟 DOM 动画冲突
@@ -72,13 +89,47 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
72
89
  this.controller.vreoUnit = vreoUnit
73
90
  this.controller.videoInstance?.pause()
74
91
 
92
+ // 预载逻辑
93
+ // 是否降低图片分辨率
94
+ if (this.$five.imageOptions.size && this.configs.imageOptions?.size && this.$five.imageOptions.size > this.configs.imageOptions.size) {
95
+ this.$five.imageOptions.size = this.configs.imageOptions.size
96
+ }
97
+
98
+ // 预载数据中的点位
99
+ if (preload || (preload === undefined && this.configs.autoPreload)) {
100
+ const panoIndexMap = vreoUnit.keyframes.filter((vreoKeyframe) => {
101
+ if (vreoKeyframe.type !== VreoKeyframeEnum.CameraMovement) {
102
+ return false
103
+ }
104
+
105
+ const data = vreoKeyframe.data as CameraMovementData
106
+ if (data.panoIndex === undefined) {
107
+ return false
108
+ }
109
+ return true
110
+ }).reduce((accu: Record<number, boolean>, curr) => {
111
+ const panoIndex = curr.data.panoIndex as number
112
+ if (!accu[panoIndex]) {
113
+ accu[panoIndex] = true
114
+ }
115
+ return accu
116
+ }, {})
117
+
118
+ const panoIndexs = Object.keys(panoIndexMap)
119
+ for (let i = 0; i < panoIndexs.length; i++) {
120
+ await this.$five.preloadPano(Number(panoIndexs[i]))
121
+ }
122
+ }
123
+
75
124
  // 新数据载入就绪
76
125
  this.emit('loaded', vreoUnit)
126
+ this.controller.emit('loaded', vreoUnit)
127
+
77
128
  if (vreoUnit.video.url) {
78
129
  if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
79
130
  this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
80
131
  }
81
- await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
132
+ await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url, currentTime / 1000)
82
133
  this.play()
83
134
  }
84
135
  this.controller.run((type, keyframe) => this.emit(type, keyframe))
@@ -89,8 +140,12 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
89
140
  return !this.controller.playing
90
141
  }
91
142
 
92
- play() {
143
+ play(currentTime?: number) {
93
144
  if (this.controller.playing) return true
145
+ if (currentTime && this.controller.videoInstance) {
146
+ // Object.assign(window, {$vreoController: this.controller})
147
+ this.controller.videoInstance.currentTime = currentTime / 1000
148
+ }
94
149
  this.controller.setPlaying(true)
95
150
  return true
96
151
  }
@@ -0,0 +1,26 @@
1
+ import * as React from 'react'
2
+ import classNames from 'classnames'
3
+ import { observer } from 'mobx-react'
4
+ import { Controller } from '../../Controller'
5
+ import { useController } from '../../hooks'
6
+
7
+ const PopUpView = observer(({ controller }: { controller: Controller }) => {
8
+
9
+ return (
10
+ <div
11
+ className={classNames('vreo-PopUp', {
12
+ 'vreo-PopUp-visible': controller.popUp,
13
+ })}
14
+ onClick={() => controller.openPopUp(false)}
15
+ >
16
+ <div className="vreo-PopUp-inner">
17
+ {controller.popUp || ''}
18
+ </div>
19
+ </div>
20
+ )
21
+ })
22
+
23
+ export function PopUp() {
24
+ const controller = useController()
25
+ return <PopUpView controller={controller} />
26
+ }
@@ -64,6 +64,7 @@ const cacheInstance: {
64
64
 
65
65
  export interface VideoAgentMeshOptions {
66
66
  videoInstance?: HTMLVideoElement
67
+ audioInstance?: HTMLAudioElement
67
68
  }
68
69
 
69
70
  /**
@@ -134,10 +135,9 @@ export class VideoAgentMesh extends THREE.Mesh {
134
135
  this.freeze = false
135
136
  this.paused = true
136
137
 
137
- {
138
+ if (!options.audioInstance) {
138
139
  if (cacheInstance.audioInstance) {
139
140
  this.audioInstance = cacheInstance.audioInstance
140
-
141
141
  } else {
142
142
  const audioInstance = document.createElement('audio')
143
143
  audioInstance.crossOrigin = ''
@@ -151,7 +151,8 @@ export class VideoAgentMesh extends THREE.Mesh {
151
151
  this.audioInstance = audioInstance
152
152
  cacheInstance.audioInstance = audioInstance
153
153
  }
154
-
154
+ } else {
155
+ this.audioInstance = options.audioInstance
155
156
  }
156
157
 
157
158
  makeObservable(this, { paused: observable })
@@ -195,7 +196,7 @@ export class VideoAgentMesh extends THREE.Mesh {
195
196
  this.videoInstance.addEventListener('timeupdate', onStart, false)
196
197
  }
197
198
 
198
- async play(videoUrl = '') {
199
+ async play(videoUrl = '', currentTime = 0) {
199
200
  videoUrl = videoUrl || ''
200
201
  if (!videoUrl) {
201
202
  if (this.videoUrl) await this.videoInstance.play()
@@ -204,7 +205,7 @@ export class VideoAgentMesh extends THREE.Mesh {
204
205
  }
205
206
 
206
207
  if (videoUrl === this.videoUrl) {
207
- this.videoInstance.currentTime = 0
208
+ this.videoInstance.currentTime = currentTime
208
209
  await this.videoInstance.play()
209
210
  return true
210
211
  }
@@ -215,7 +216,7 @@ export class VideoAgentMesh extends THREE.Mesh {
215
216
 
216
217
  return await new Promise((resolve) =>
217
218
  setTimeout(async () => {
218
- this.videoInstance.currentTime = 0
219
+ this.videoInstance.currentTime = currentTime
219
220
  await this.videoInstance.play()
220
221
  resolve(true)
221
222
  }, 20),
@@ -9,7 +9,7 @@ export class VideoAgentScene {
9
9
  renderer = new THREE.WebGLRenderer({ alpha: true })
10
10
  container: HTMLElement
11
11
 
12
- constructor(container: HTMLElement, needRender = true) {
12
+ constructor(container: HTMLElement, needRender = true, options: { videoInstance?: HTMLVideoElement, audioInstance?: HTMLAudioElement } = {}) {
13
13
  this.container = container
14
14
  this.camera.position.set(0, 0, 10)
15
15
  this.camera.lookAt(0, 0, 0)
@@ -22,7 +22,7 @@ export class VideoAgentScene {
22
22
  this.renderer.setSize(state.width * window.devicePixelRatio, state.height * window.devicePixelRatio)
23
23
  domElement.setAttribute('style', `width: ${state.width}px;height: ${state.height}px;`)
24
24
 
25
- this.videoAgentMesh = new VideoAgentMesh(480, 270, 1, 1)
25
+ this.videoAgentMesh = new VideoAgentMesh(480, 270, 1, 1, options)
26
26
  if (needRender) {
27
27
  container.append(domElement)
28
28
  this.scene.add(this.videoAgentMesh)
@@ -1,8 +1,9 @@
1
1
  import * as React from 'react'
2
2
  import { useController } from '../../hooks'
3
+ import { VideoAgentMeshOptions } from './VideoAgentMesh'
3
4
  import { VideoAgentScene } from './VideoAgentScene'
4
5
 
5
- export function VideoAgent(props: { onClick?: () => void }) {
6
+ export function VideoAgent(props: { onClick?: () => void; options?: VideoAgentMeshOptions }) {
6
7
  const ref = React.useRef<HTMLDivElement>(null)
7
8
  const controller = useController()
8
9
 
@@ -12,7 +13,7 @@ export function VideoAgent(props: { onClick?: () => void }) {
12
13
  console.warn('"VideoAgentScene" 重复初始化,已被过滤 ...')
13
14
  return
14
15
  }
15
- const videoAgentScene = new VideoAgentScene(ref.current)
16
+ const videoAgentScene = new VideoAgentScene(ref.current, true, props.options || {})
16
17
  controller.videoAgentScene = videoAgentScene
17
18
 
18
19
  return () => {
@@ -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.move(data, end - start)
27
+ await ref.current.rotate(data as RotateArgs, end - start)
24
28
  }
25
29
  }
26
30
 
@@ -1,13 +1,19 @@
1
1
  import * as React from 'react'
2
2
  import { ReactNode } from 'react'
3
- import { InfoPanelData, InfoPanelTypeEnum, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
3
+ import {
4
+ InfoPanelData,
5
+ InfoPanelStyleEnum,
6
+ InfoPanelTypeEnum,
7
+ VreoKeyframe,
8
+ VreoKeyframeEnum,
9
+ } from '../../../../typings/VreoUnit'
4
10
  import { useController } from '../../../hooks'
5
11
 
6
12
  function InfoPanelImg({ url, children }: { url: string; children?: ReactNode }) {
7
13
  return (
8
14
  <div className="vreo-infoPanel vreo-infoPanel--img">
9
15
  {children}
10
- <div className="vreo-infoPanelImg" style={{backgroundImage: `url(${url})`}} ></div>
16
+ <div className="vreo-infoPanelImg" style={{ backgroundImage: `url(${url})` }}></div>
11
17
  </div>
12
18
  )
13
19
  }
@@ -16,7 +22,9 @@ function InfoPanelVideo({ url, children }: { url: string; children?: ReactNode }
16
22
  return (
17
23
  <div className="vreo-infoPanel vreo-infoPanel--video">
18
24
  {children}
19
- <video playsInline autoPlay className="vreo-infoPanelVideo" src={url} />
25
+ <div className="vreo-infoPanelWrapper">
26
+ <video playsInline autoPlay className="vreo-infoPanelVideo" src={url} />
27
+ </div>
20
28
  </div>
21
29
  )
22
30
  }
@@ -31,10 +39,12 @@ const Title = (props: TitleProps) => {
31
39
  return null
32
40
  }
33
41
 
34
- return <div className="vreo-infoPanel-title">
35
- <div className="vreo-infoPanel-t1">{props.title}</div>
36
- <div className="vreo-infoPanel-t2">{props.subTitle}</div>
37
- </div>
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>
46
+ </div>
47
+ )
38
48
  }
39
49
 
40
50
  export function InfoPanel() {
@@ -45,31 +55,88 @@ export function InfoPanel() {
45
55
  if (controller.configs?.keyframeMap.InfoPanel === false) {
46
56
  return
47
57
  }
58
+
48
59
  const callback = (keyframe: VreoKeyframe) => {
49
60
  const { start, end, data } = keyframe
50
61
 
51
62
  const infoPanelData = data as InfoPanelData
52
-
53
63
 
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)
54
102
 
55
- if (infoPanelData.type === InfoPanelTypeEnum.Image) {
56
- controller.openDrawer({ content: <InfoPanelImg url={infoPanelData.url} />, height: '60vh' })
57
- } else if (infoPanelData.type === InfoPanelTypeEnum.Video) {
58
- controller.openDrawer({ content: <InfoPanelVideo url={infoPanelData.url} />, height: '60vh' })
59
- }
60
- timeoutRef.current = setTimeout(() => controller.openDrawer(false), end - start)
103
+ timeoutRef.current = setTimeout(() => {
104
+ controller.openDrawer(false)
105
+ controller.openPopUp(false)
106
+ }, end - start)
61
107
  }
62
108
  controller.on(VreoKeyframeEnum.InfoPanel, callback)
63
109
 
64
- Object.assign(window, { $setInfoPanel: () => {
65
- controller.openDrawer({ content: (
66
-
67
- // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/seesay/tools/cat_music___f68fb9bbe1f7cd6d00a16456dd0b09ad.gif'>
68
- <InfoPanelImg url='http://vrlab-public.ljcdn.com/common/images/web/d94e1bd7-0311-4b20-9c41-a1294fe43554.png'>
69
- <Title title="场景联动抓拍图片" subTitle={"2022.02.17 14:00"} />
70
- </InfoPanelImg>
71
- ), height: '60vh' })
72
- }})
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
+ // })
73
140
 
74
141
  return () => {
75
142
  controller.off(VreoKeyframeEnum.InfoPanel, callback)