@realsee/vreo 0.2.0-alpha.6 → 0.2.0-alpha.9
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 +47 -0
- package/docs/assets/search.js +1 -1
- package/docs/classes/Player.Controller.html +3 -3
- package/docs/classes/Player.Player-1.html +3 -3
- package/docs/classes/Player.VideoAgentMesh.html +11 -11
- package/docs/classes/Player.VideoAgentScene.html +1 -1
- package/docs/enums/Player.InfoPanelStyleEnum.html +1 -1
- package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
- package/docs/enums/Player.PanoEffectEnum.html +1 -1
- package/docs/enums/Player.PanoTagEnum.html +1 -1
- package/docs/enums/Player.VreoKeyframeEnum.html +12 -12
- package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
- package/docs/enums/fivePlugins.Rotation.html +1 -1
- package/docs/index.html +21 -1
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -1
- package/docs/interfaces/Player.PlayerConfigs.html +3 -3
- package/docs/interfaces/Player.Vertex.html +1 -1
- package/docs/interfaces/Player.VideoAgentMeshOptions.html +1 -1
- 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 +2 -2
- 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 +6 -6
- package/docs/interfaces/react.VreoProviderProps.html +1 -1
- package/docs/modules/Player.html +13 -13
- package/docs/modules/custom.html +1 -1
- package/docs/modules/fivePlugins.html +2 -2
- package/docs/modules/react.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 +4 -3
- package/lib/Player/custom/SpatialScenePanel/index.js +86 -14
- package/lib/Player/index.d.ts +1 -1
- package/lib/Player/index.js +68 -9
- 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/CameraMovement/index.js +41 -5
- package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +23 -15
- package/lib/Player/typings.d.ts +6 -0
- package/lib/fivePlugins/CameraMovementPlugin/index.js +101 -90
- package/lib/fivePlugins/CameraMovementPlugin/typings.d.ts +3 -2
- package/lib/typings/VreoUnit.d.ts +4 -3
- package/package.json +2 -2
- package/resources/PlayController/createHTMLAudioElement.ts +53 -0
- package/resources/PlayController/index.ts +167 -0
- package/resources/Player/App.tsx +2 -0
- package/resources/Player/custom/SpatialScenePanel/index.tsx +84 -8
- package/resources/Player/index.tsx +34 -2
- 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/CameraMovement/index.tsx +7 -3
- package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +20 -15
- package/resources/Player/typings.ts +5 -0
- package/resources/fivePlugins/CameraMovementPlugin/index.ts +55 -47
- package/resources/fivePlugins/CameraMovementPlugin/typings.ts +2 -1
- package/resources/typings/VreoUnit.ts +5 -4
- package/stylesheets/custom/SpatialScenePanel.css +14 -8
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import ReactDOM from 'react-dom'
|
|
3
3
|
import { Five } from '@realsee/five'
|
|
4
|
-
import
|
|
4
|
+
import * as THREE from 'three'
|
|
5
|
+
import { Object3D, Raycaster, Vector3 } from 'three'
|
|
5
6
|
import { tweenProgress } from '@realsee/dnalogel/shared-utils/animationFrame/BetterTween'
|
|
6
7
|
import { CSS3DRenderPlugin, CSS3DRenderPluginExportType } from '@realsee/dnalogel/plugins/CSS3DRenderPlugin'
|
|
7
8
|
|
|
8
9
|
import { VreoKeyframe, VreoKeyframeEnum } from '../../../typings/VreoUnit'
|
|
9
10
|
import { CustomVreoKeyframeProps } from '../../typings'
|
|
10
11
|
|
|
12
|
+
// __debug__
|
|
11
13
|
// const mockData: SpatialScenePanelData = {
|
|
12
14
|
// customType: 'SpatialScenePanel',
|
|
13
15
|
// "stateList": [
|
|
@@ -66,6 +68,7 @@ const searchV1 = ({ five, dom }: SearchParams) => {
|
|
|
66
68
|
const [intersect] = five.model.intersectRaycaster(new Raycaster(cameraPosition, cameraDirection))
|
|
67
69
|
const point = five.project2d(intersect.point)
|
|
68
70
|
|
|
71
|
+
const widescreen = window.innerWidth > 560 ? true : false
|
|
69
72
|
// const width = dom!.clientWidth
|
|
70
73
|
const height = dom!.clientHeight
|
|
71
74
|
dom!.style.left = point!.x + 'px'
|
|
@@ -79,8 +82,8 @@ const searchV1 = ({ five, dom }: SearchParams) => {
|
|
|
79
82
|
const rightBottom = new Vector3(right, bottom)
|
|
80
83
|
|
|
81
84
|
const points = [leftBottom, rightBottom, rightTop, leftTop].map((point) => {
|
|
82
|
-
point.setX((point.x / window.innerWidth) * 2 - 1.25)
|
|
83
|
-
point.setY(-(point.y / window.innerHeight) * 2 + 1)
|
|
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))
|
|
84
87
|
point.setZ(0.5)
|
|
85
88
|
return point.unproject(five.camera).addScaledVector(cameraDirection, 0.2)
|
|
86
89
|
})
|
|
@@ -89,7 +92,8 @@ const searchV1 = ({ five, dom }: SearchParams) => {
|
|
|
89
92
|
// const colors = [0xdc143c, 0xffff00, 0x0000ff, 0x008000]
|
|
90
93
|
// points.forEach((p, index) => five.scene.add(getSphere(p, colors[index])))
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
// 判断是手机 150
|
|
96
|
+
const ratio = leftBottom.distanceTo(rightBottom) / (widescreen ? 150 : 120)
|
|
93
97
|
return { points, ratio }
|
|
94
98
|
}
|
|
95
99
|
|
|
@@ -98,6 +102,7 @@ const searchV1 = ({ five, dom }: SearchParams) => {
|
|
|
98
102
|
* @returns
|
|
99
103
|
*/
|
|
100
104
|
export function SpatialScenePanel(props: CustomVreoKeyframeProps) {
|
|
105
|
+
const timeoutRef = React.useRef<NodeJS.Timeout | null>(null)
|
|
101
106
|
const ref = React.useRef<HTMLDivElement>(null)
|
|
102
107
|
const panelRef = React.useRef<HTMLDivElement | null>(null)
|
|
103
108
|
const rendererRef = React.useRef<CSS3DRenderPluginExportType>(CSS3DRenderPlugin(props.five))
|
|
@@ -123,16 +128,19 @@ export function SpatialScenePanel(props: CustomVreoKeyframeProps) {
|
|
|
123
128
|
const { container, dispose, css3DObject, render } =
|
|
124
129
|
rendererRef.current.create3DDomContainer(points, { ratio, autoRender: false }) || {}
|
|
125
130
|
|
|
131
|
+
Object.assign(window, { $css3DObject: css3DObject })
|
|
126
132
|
if (!container) return
|
|
127
133
|
|
|
128
134
|
ReactDOM.render(<Panel ref={(ref) => (panelRef.current = ref)} data={data} />, container)
|
|
129
135
|
const startRotateY = -(Math.PI * 2) / 9
|
|
130
136
|
let lastRotateY = 0
|
|
137
|
+
|
|
131
138
|
tweenProgress(1000)
|
|
132
139
|
.onUpdate(({ progress }) => {
|
|
133
140
|
const needRotateY = (Math.PI / 90) * 11 * progress
|
|
134
141
|
const rotateY = needRotateY - lastRotateY
|
|
135
142
|
css3DObject?.rotateY(rotateY)
|
|
143
|
+
// css3DObject?.rotateZ
|
|
136
144
|
lastRotateY = needRotateY
|
|
137
145
|
})
|
|
138
146
|
.onStart(() => {
|
|
@@ -143,30 +151,70 @@ export function SpatialScenePanel(props: CustomVreoKeyframeProps) {
|
|
|
143
151
|
panelRef.current?.classList.add('show')
|
|
144
152
|
})
|
|
145
153
|
.play()
|
|
154
|
+
|
|
155
|
+
// Object.assign(window, { $dispose: () => {
|
|
156
|
+
// panelRef.current?.classList.add('hide')
|
|
157
|
+
// setTimeout(() => dispose?.(), 1500)
|
|
158
|
+
// } })
|
|
159
|
+
|
|
146
160
|
const { start, end } = keyframe
|
|
147
161
|
|
|
148
|
-
setTimeout(() => {
|
|
162
|
+
timeoutRef.current = setTimeout(() => {
|
|
149
163
|
panelRef.current?.classList.add('hide')
|
|
150
|
-
setTimeout(() =>
|
|
164
|
+
timeoutRef.current = setTimeout(() => {
|
|
165
|
+
dispose?.()
|
|
166
|
+
timeoutRef.current = null
|
|
167
|
+
}, 1500)
|
|
151
168
|
}, end - start)
|
|
152
169
|
}
|
|
153
170
|
|
|
154
|
-
|
|
171
|
+
Object.assign(window, { $callback: callback })
|
|
172
|
+
|
|
173
|
+
// setTimeout(() => {callback()}, 8000)
|
|
155
174
|
props.subscribe.on(VreoKeyframeEnum.Custom, callback)
|
|
156
175
|
|
|
157
176
|
return () => {
|
|
158
177
|
props.subscribe.off(VreoKeyframeEnum.Custom, callback)
|
|
178
|
+
if (timeoutRef.current) {
|
|
179
|
+
clearTimeout(timeoutRef.current)
|
|
180
|
+
}
|
|
159
181
|
}
|
|
160
182
|
}, [])
|
|
161
183
|
|
|
162
184
|
return <div className="vreo-SpatialScenePanel" ref={ref}></div>
|
|
163
185
|
}
|
|
164
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
|
+
|
|
165
213
|
const Panel = React.forwardRef(
|
|
166
214
|
(props: { data: SpatialScenePanelData }, myRef: React.LegacyRef<HTMLDivElement> | undefined) => (
|
|
167
215
|
<div className="SpatialScenePanel" ref={myRef}>
|
|
168
216
|
<div className="SpatialScenePanel-show-area">
|
|
169
|
-
<
|
|
217
|
+
<SpatialScenePanelBg />
|
|
170
218
|
<div className="SpatialScenePanel-header">
|
|
171
219
|
<div className="SpatialScenePanel-title">{props.data?.title}</div>
|
|
172
220
|
<div className="SpatialScenePanel-temperature">{props.data?.temperature}℃</div>
|
|
@@ -186,3 +234,31 @@ const Panel = React.forwardRef(
|
|
|
186
234
|
</div>
|
|
187
235
|
)
|
|
188
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,7 +4,7 @@ import { Five, Subscribe } from '@realsee/five'
|
|
|
4
4
|
|
|
5
5
|
import { App } from './App'
|
|
6
6
|
import { Controller, ControllerContext } from './Controller'
|
|
7
|
-
import { VreoKeyframeEvent, 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'
|
|
@@ -69,7 +69,7 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
69
69
|
)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
async load(vreoUnit: VreoUnit, currentTime = 0) {
|
|
72
|
+
async load(vreoUnit: VreoUnit, currentTime = 0, preload = false) {
|
|
73
73
|
if (!this.controller.visible) {
|
|
74
74
|
this.controller.setVisible(true)
|
|
75
75
|
// 延迟 500ms 规避跟 DOM 动画冲突
|
|
@@ -86,6 +86,38 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
86
86
|
this.controller.vreoUnit = vreoUnit
|
|
87
87
|
this.controller.videoInstance?.pause()
|
|
88
88
|
|
|
89
|
+
// 预载逻辑
|
|
90
|
+
// 是否降低图片分辨率
|
|
91
|
+
if (this.$five.imageOptions.size && this.configs.imageOptions?.size && this.$five.imageOptions.size > this.configs.imageOptions.size) {
|
|
92
|
+
this.$five.imageOptions.size = this.configs.imageOptions.size
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 预载数据中的点位
|
|
96
|
+
if (preload || (preload === undefined && this.configs.autoPreload)) {
|
|
97
|
+
const panoIndexMap = vreoUnit.keyframes.filter((vreoKeyframe) => {
|
|
98
|
+
if (vreoKeyframe.type !== VreoKeyframeEnum.CameraMovement) {
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const data = vreoKeyframe.data as CameraMovementData
|
|
103
|
+
if (data.panoIndex === undefined) {
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
return true
|
|
107
|
+
}).reduce((accu: Record<number, boolean>, curr) => {
|
|
108
|
+
const panoIndex = curr.data.panoIndex as number
|
|
109
|
+
if (!accu[panoIndex]) {
|
|
110
|
+
accu[panoIndex] = true
|
|
111
|
+
}
|
|
112
|
+
return accu
|
|
113
|
+
}, {})
|
|
114
|
+
|
|
115
|
+
const panoIndexs = Object.keys(panoIndexMap)
|
|
116
|
+
for (let i = 0; i < panoIndexs.length; i++) {
|
|
117
|
+
await this.$five.preloadPano(Number(panoIndexs[i]))
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
89
121
|
// 新数据载入就绪
|
|
90
122
|
this.emit('loaded', vreoUnit)
|
|
91
123
|
if (vreoUnit.video.url) {
|
|
@@ -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 })
|
|
@@ -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.
|
|
27
|
+
await ref.current.rotate(data as RotateArgs, end - start)
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -6,49 +6,52 @@ import { UpdateVRPanoramaData, VreoKeyframe, VreoKeyframeEnum } from '../../../.
|
|
|
6
6
|
export function UpdateVRPanorama() {
|
|
7
7
|
const controller = useController()
|
|
8
8
|
const five = useFiveInstance()
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const deafultWorkRef = React.useRef<string[] | null>(null)
|
|
10
|
+
const updateWorkRef = React.useRef<Work | null>(null)
|
|
11
11
|
|
|
12
12
|
const restoreCallback = React.useCallback(() => {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
if (deafultWorkRef.current) {
|
|
15
|
+
const work = parseWork(deafultWorkRef.current)
|
|
15
16
|
five.load(work)
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
updateWorkRef.current = null
|
|
19
20
|
}, [])
|
|
20
21
|
|
|
21
22
|
const pausedCallback = React.useCallback(() => {
|
|
22
|
-
if (
|
|
23
|
-
const work = parseWork(
|
|
23
|
+
if (deafultWorkRef.current) {
|
|
24
|
+
const work = parseWork(deafultWorkRef.current)
|
|
25
|
+
Object.assign(window, {$rawWork: work})
|
|
24
26
|
five.load(work)
|
|
25
27
|
}
|
|
26
28
|
}, [])
|
|
27
29
|
|
|
28
30
|
const playingCallback = React.useCallback(() => {
|
|
29
|
-
if (!
|
|
31
|
+
if (!updateWorkRef.current) {
|
|
30
32
|
return
|
|
31
33
|
}
|
|
32
|
-
five.load(
|
|
34
|
+
five.load(updateWorkRef.current)
|
|
33
35
|
}, [])
|
|
34
36
|
|
|
35
37
|
React.useEffect(() => {
|
|
36
38
|
const callback = (keyframe: VreoKeyframe) => {
|
|
37
|
-
if (!
|
|
38
|
-
|
|
39
|
+
if (!deafultWorkRef.current) {
|
|
40
|
+
deafultWorkRef.current = five.work.raw.works
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
const data = keyframe.data as UpdateVRPanoramaData
|
|
42
44
|
|
|
43
45
|
// 如果数据中有新 work 数据,则直接载入
|
|
44
46
|
if (data.work) {
|
|
45
|
-
|
|
46
|
-
five.load(
|
|
47
|
+
updateWorkRef.current = parseWork(data.work)
|
|
48
|
+
five.load(updateWorkRef.current)
|
|
47
49
|
return
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
const lastRawWork = five.work?.raw.works[0]
|
|
51
53
|
|
|
54
|
+
|
|
52
55
|
// 动态场景:不提供完成的签名数据,需重新整理
|
|
53
56
|
if (data.dynamic_scene && !data.panorama) {
|
|
54
57
|
const lastWork = JSON.parse(lastRawWork)
|
|
@@ -59,8 +62,10 @@ export function UpdateVRPanorama() {
|
|
|
59
62
|
delete data.dynamic_scene
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
Object.assign(window, {$work1: JSON.parse(lastRawWork), $work2: data, parseWork: parseWork})
|
|
66
|
+
|
|
67
|
+
updateWorkRef.current = parseWork([lastRawWork, data])
|
|
68
|
+
five.load(updateWorkRef.current)
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
controller.on(VreoKeyframeEnum.UpdateVRPanorama, callback)
|
|
@@ -2,6 +2,7 @@ import React, { ReactNode } from 'react';
|
|
|
2
2
|
import { Subscribe, Five } from '@realsee/five';
|
|
3
3
|
|
|
4
4
|
import { VreoKeyframeConfigMap, VreoKeyframeEvent } from '../typings/VreoUnit'
|
|
5
|
+
import { VideoAgentMeshOptions } from './modules/VideoAgent/VideoAgentMesh';
|
|
5
6
|
|
|
6
7
|
export interface PlayerConfigs {
|
|
7
8
|
containter?: ReactDOM.Container
|
|
@@ -15,11 +16,15 @@ export interface PlayerConfigs {
|
|
|
15
16
|
videoEffect?: HTMLVideoElement
|
|
16
17
|
modelTVVideo?: HTMLVideoElement
|
|
17
18
|
}
|
|
19
|
+
|
|
20
|
+
videoAgentMeshOptions?: VideoAgentMeshOptions
|
|
18
21
|
/**
|
|
19
22
|
* 如果需要在 底部面板添加自定义内容,可以传递个 React 组件。
|
|
20
23
|
*/
|
|
21
24
|
customPanelChildren?: ReactNode
|
|
22
25
|
customKeyframes?: React.FC<CustomVreoKeyframeProps>[]
|
|
26
|
+
imageOptions?: { size: number }
|
|
27
|
+
autoPreload?: boolean
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export type VreoSubscribe = Pick<Subscribe<VreoKeyframeEvent>, 'on' | 'once' | 'off'>
|
|
@@ -50,65 +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
|
-
const movePanoOptions: MovePanoOptions = {
|
|
108
|
+
const movePanoOptions: MovePanoOptions = Object.assign(args, {
|
|
101
109
|
duration, // 移动耗时
|
|
102
110
|
moveEndCallback: () => resolve(true), // 移动结束
|
|
103
|
-
moveCancelCallback: () =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
moveCancelCallback: () => {
|
|
112
|
+
resolve(true)
|
|
113
|
+
}, // 移动开始
|
|
114
|
+
// effect: args.transEffect || 'fade',
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await five.moveToPano(
|
|
107
118
|
panoIndex,
|
|
108
|
-
|
|
109
|
-
movePanoOptions,
|
|
110
|
-
args,
|
|
111
|
-
),
|
|
119
|
+
movePanoOptions,
|
|
112
120
|
)
|
|
113
121
|
} else {
|
|
114
122
|
reject(false)
|
|
@@ -39,7 +39,8 @@ export interface CameraMovementOptsCallback {
|
|
|
39
39
|
export type MoveArgs = {
|
|
40
40
|
mode: Mode
|
|
41
41
|
panoIndex: number
|
|
42
|
-
|
|
42
|
+
transEffect?: "fly" | "fade" | "instant"
|
|
43
|
+
} & Pose
|
|
43
44
|
|
|
44
45
|
export type MoveOpts = {
|
|
45
46
|
preload?: boolean
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mode, Pose } from '@realsee/five'
|
|
1
|
+
import { Mode, MovePanoOptions, Pose } from '@realsee/five'
|
|
2
2
|
import { CameraMovementEffect, Rotation } from '../fivePlugins/CameraMovementPlugin/typings'
|
|
3
3
|
|
|
4
4
|
export enum VreoKeyframeEnum {
|
|
@@ -65,7 +65,7 @@ export type VreoKeyframeConfigMap = {
|
|
|
65
65
|
* 剧本关键帧
|
|
66
66
|
*/
|
|
67
67
|
export interface VreoKeyframe {
|
|
68
|
-
uuid
|
|
68
|
+
uuid?: string
|
|
69
69
|
type: VreoKeyframeEnum
|
|
70
70
|
start: number
|
|
71
71
|
end: number
|
|
@@ -104,7 +104,7 @@ export type VreoKeyframeEvent = { [key in VreoKeyframeEnum]: (keyframe: VreoKeyf
|
|
|
104
104
|
// 新数据载入完成
|
|
105
105
|
loaded: (vreoUnit: VreoUnit) => void
|
|
106
106
|
// 语音状态 播放 -> 暂停
|
|
107
|
-
paused: () => void
|
|
107
|
+
paused: (ended?: boolean) => void
|
|
108
108
|
// 语音状态 暂停 -> 播放
|
|
109
109
|
playing: () => void
|
|
110
110
|
// 未知的 剧本帧类型
|
|
@@ -115,7 +115,8 @@ export type VreoKeyframeEvent = { [key in VreoKeyframeEnum]: (keyframe: VreoKeyf
|
|
|
115
115
|
* 相机运动
|
|
116
116
|
*/
|
|
117
117
|
export type CameraMovementData = {
|
|
118
|
-
effect
|
|
118
|
+
effect?: CameraMovementEffect
|
|
119
|
+
transEffect?: "fly" | "fade" | "instant"
|
|
119
120
|
mode: Mode
|
|
120
121
|
panoIndex: number
|
|
121
122
|
loop?: boolean
|
|
@@ -77,9 +77,15 @@
|
|
|
77
77
|
background-image: url("//vrlab-static.ljcdn.com/release/web/VoiceAssistant/images/panel-min.7d9ba2b7.png");
|
|
78
78
|
background-size: 340rem 13.4375rem;
|
|
79
79
|
background-repeat: no-repeat;
|
|
80
|
-
|
|
80
|
+
z-index: -1;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
.SpatialScenePanel-bg--animation {
|
|
84
|
+
/* animation: SpatialScenePanel-panel-sprites-animation 1.375s 0s steps(33) infinite normal; */
|
|
85
|
+
animation: SpatialScenePanel-panel-sprites-animation 1.375s 0.5s steps(33) normal;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
83
89
|
.SpatialScenePanel-show-area .SpatialScenePanel-header {
|
|
84
90
|
width: 7.5rem;
|
|
85
91
|
height: 1.375rem;
|
|
@@ -89,7 +95,9 @@
|
|
|
89
95
|
background-image: url("//vrlab-static.ljcdn.com/release/web/VoiceAssistant/images/title-bg.377af865.png");
|
|
90
96
|
background-size: 100%;
|
|
91
97
|
margin: 1.875rem auto 1.25rem auto;
|
|
92
|
-
|
|
98
|
+
background-image: linear-gradient(to left, rgba(234, 208, 154, 0), rgb(255 229 176 / 21%) 47%, rgba(234, 208, 154, 0));
|
|
99
|
+
border-bottom: 1px solid rgb(255 255 255 / 10%);
|
|
100
|
+
border-radius: 2px;
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
.SpatialScenePanel-show-area .SpatialScenePanel-header .SpatialScenePanel-title {
|
|
@@ -97,7 +105,7 @@
|
|
|
97
105
|
font-size: 1.0625rem;
|
|
98
106
|
color: #ffe5b0;
|
|
99
107
|
letter-spacing: 0;
|
|
100
|
-
line-height: 1.
|
|
108
|
+
line-height: 1.125;
|
|
101
109
|
text-shadow: 0 0 1.25rem rgba(0,0,0,0.15)
|
|
102
110
|
}
|
|
103
111
|
|
|
@@ -106,7 +114,7 @@
|
|
|
106
114
|
font-size: .625rem;
|
|
107
115
|
color: rgba(255,229,176,0.6);
|
|
108
116
|
letter-spacing: 0;
|
|
109
|
-
line-height: .
|
|
117
|
+
line-height: 1.25rem;
|
|
110
118
|
text-shadow: 0 0 .625rem rgba(255,255,255,0.03);
|
|
111
119
|
align-self: flex-end
|
|
112
120
|
}
|
|
@@ -270,9 +278,7 @@
|
|
|
270
278
|
|
|
271
279
|
.SpatialScenePanel.hide .SpatialScenePanel-show-area {
|
|
272
280
|
transform: scale3d(0,1,1);
|
|
273
|
-
transition:
|
|
274
|
-
transition: transform 500ms linear;
|
|
275
|
-
transition: transform 500ms linear, -webkit-transform 500ms linear
|
|
281
|
+
transition: transform 150ms linear;
|
|
276
282
|
}
|
|
277
283
|
|
|
278
284
|
.SpatialScenePanel.hide .SpatialScenePanel-disappear-area {
|
|
@@ -298,6 +304,6 @@
|
|
|
298
304
|
background-image: url("//vrlab-static.ljcdn.com/release/web/VoiceAssistant/images/line.4ac1c0bb.png");
|
|
299
305
|
background-size: 10rem 11.666666666666666rem;
|
|
300
306
|
background-repeat: no-repeat;
|
|
301
|
-
animation: SpatialScenePanel-line-sprites-animation 500ms
|
|
307
|
+
animation: SpatialScenePanel-line-sprites-animation 500ms 100ms steps(23) 1 normal
|
|
302
308
|
}
|
|
303
309
|
|