@realsee/vreo 1.0.0-alpha.19 → 1.0.0-alpha.20
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/lib/Player/modules/keyframes/BgMusic/index.js +2 -4
- package/package.json +1 -3
- package/docs/.nojekyll +0 -1
- package/docs/assets/custom.css +0 -78
- package/docs/assets/highlight.css +0 -127
- package/docs/assets/icons.css +0 -1043
- package/docs/assets/icons.png +0 -0
- package/docs/assets/icons@2x.png +0 -0
- package/docs/assets/main.js +0 -52
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1414
- package/docs/assets/widgets.png +0 -0
- package/docs/assets/widgets@2x.png +0 -0
- package/docs/classes/Player.AudioLike.html +0 -52
- package/docs/classes/Player.Controller.html +0 -54
- package/docs/classes/Player.Player-1.html +0 -50
- package/docs/classes/Player.VideoAgentMesh.html +0 -142
- package/docs/classes/Player.VideoAgentScene.html +0 -1
- package/docs/demo/assets/AppReact.20163f9a.js +0 -1
- package/docs/demo/assets/default.17872c62.css +0 -1
- package/docs/demo/assets/default.5069891b.js +0 -3988
- package/docs/demo/assets/dynamic.c8118cc9.js +0 -1
- package/docs/demo/assets/examples.5391fc1f.js +0 -25
- package/docs/demo/assets/examples.dac4a6fe.css +0 -1
- package/docs/demo/assets/index.2272a9ef.js +0 -1
- package/docs/demo/assets/index.9331038f.css +0 -1
- package/docs/demo/assets/main.b335b989.js +0 -1
- package/docs/demo/assets/react.2ee8565f.css +0 -1
- package/docs/demo/assets/react.efea3f3f.js +0 -25
- package/docs/demo/assets/znRoyv06SZQeqA7m.0057e8ae.js +0 -1
- package/docs/demo/examples.html +0 -17
- package/docs/demo/index-react-dynamic.html +0 -20
- package/docs/demo/index-react.html +0 -20
- package/docs/demo/index.html +0 -19
- package/docs/enums/Player.InfoPanelStyleEnum.html +0 -1
- package/docs/enums/Player.InfoPanelTypeEnum.html +0 -3
- package/docs/enums/Player.PanoEffectEnum.html +0 -5
- package/docs/enums/Player.PanoTagEnum.html +0 -3
- package/docs/enums/Player.PanoTagStyleEnum.html +0 -7
- package/docs/enums/Player.VreoKeyframeEnum.html +0 -25
- package/docs/enums/fivePlugins.CameraMovementEffect.html +0 -1
- package/docs/enums/fivePlugins.Rotation.html +0 -1
- package/docs/index.html +0 -248
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +0 -1
- package/docs/interfaces/Player.PlayerConfigs.html +0 -7
- package/docs/interfaces/Player.Vertex.html +0 -3
- package/docs/interfaces/Player.VideoAgentMeshOptions.html +0 -8
- package/docs/interfaces/Player.VreoKeyframe.html +0 -3
- package/docs/interfaces/Player.VreoUnit.html +0 -3
- package/docs/interfaces/Player.VreoVideo.html +0 -3
- package/docs/interfaces/fivePlugins.CSS3DRenderPluginExportType.html +0 -4
- package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +0 -1
- package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +0 -7
- package/docs/interfaces/fivePlugins.CameraMovementPluginParameterType.html +0 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +0 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +0 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +0 -1
- package/docs/interfaces/fivePlugins.Vector3Position.html +0 -3
- package/docs/interfaces/react.VreoActionCallbacks.html +0 -23
- package/docs/interfaces/react.VreoProviderProps.html +0 -1
- package/docs/modules/Player.html +0 -37
- package/docs/modules/custom.html +0 -3
- package/docs/modules/fivePlugins.html +0 -6
- package/docs/modules/react.html +0 -1
- package/docs/modules.html +0 -1
- package/resources/PlayController/createHTMLAudioElement.ts +0 -53
- package/resources/PlayController/index.ts +0 -154
- package/resources/Player/App.tsx +0 -66
- package/resources/Player/Controller.ts +0 -295
- package/resources/Player/custom/SpatialScenePanel/index.tsx +0 -264
- package/resources/Player/hooks.ts +0 -26
- package/resources/Player/index.tsx +0 -227
- package/resources/Player/modules/Drawer/index.tsx +0 -40
- package/resources/Player/modules/PopUp/index.tsx +0 -26
- package/resources/Player/modules/ResizeObserver/index.tsx +0 -23
- package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +0 -302
- package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +0 -56
- package/resources/Player/modules/VideoAgent/index.tsx +0 -53
- package/resources/Player/modules/Wave/index.tsx +0 -150
- package/resources/Player/modules/keyframes/BgMusic/index.tsx +0 -75
- package/resources/Player/modules/keyframes/CameraMovement/index.tsx +0 -37
- package/resources/Player/modules/keyframes/InfoPanel/index.tsx +0 -165
- package/resources/Player/modules/keyframes/ModelVideo/index.tsx +0 -77
- package/resources/Player/modules/keyframes/PanoEffect/index.tsx +0 -99
- package/resources/Player/modules/keyframes/PanoEffect/lineAnime.ts +0 -31
- package/resources/Player/modules/keyframes/PanoTag/index.tsx +0 -83
- package/resources/Player/modules/keyframes/PanoTextLabel/index.tsx +0 -117
- package/resources/Player/modules/keyframes/Prompter/index.tsx +0 -56
- package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +0 -99
- package/resources/Player/modules/keyframes/VideoEffect/index.tsx +0 -115
- package/resources/Player/typings.ts +0 -49
- package/resources/fivePlugins/CSS3DRenderPlugin/centerPoint.ts +0 -5
- package/resources/fivePlugins/CSS3DRenderPlugin/createResizeObserver.ts +0 -17
- package/resources/fivePlugins/CSS3DRenderPlugin/evenNumber.ts +0 -4
- package/resources/fivePlugins/CSS3DRenderPlugin/index.ts +0 -254
- package/resources/fivePlugins/CSS3DRenderPlugin/transformPositionToVector3.ts +0 -5
- package/resources/fivePlugins/CameraMovementPlugin/index.ts +0 -226
- package/resources/fivePlugins/CameraMovementPlugin/typings.ts +0 -59
- package/resources/fivePlugins/ModelTVVideoPlugin/index.ts +0 -278
- package/resources/index.ts +0 -1
- package/resources/react/index.tsx +0 -121
- package/resources/shared-utils/AudioLike.ts +0 -107
- package/resources/shared-utils/Preloader.ts +0 -35
- package/resources/shared-utils/addResizeListener.ts +0 -46
- package/resources/shared-utils/animationFrame/BetterTween.ts +0 -33
- package/resources/shared-utils/animationFrame/index.ts +0 -48
- package/resources/shared-utils/animationFrame/tween.ts +0 -51
- package/resources/shared-utils/createTransMatrix.ts +0 -12
- package/resources/shared-utils/getFileExpandedName.ts +0 -6
- package/resources/shared-utils/getMediaInfo.ts +0 -52
- package/resources/shared-utils/setElementDataset.ts +0 -18
- package/resources/typings/VreoUnit.ts +0 -314
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import { Five, MovePanoOptions } from '@realsee/five'
|
|
2
|
-
import type { FivePlugin } from '@realsee/five'
|
|
3
|
-
import * as TWEEN from '@tweenjs/tween.js'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
CameraMovementPluginParameterType,
|
|
7
|
-
CameraMovementPluginExportType,
|
|
8
|
-
MoveArgs,
|
|
9
|
-
MoveOpts,
|
|
10
|
-
RotateArgs,
|
|
11
|
-
RotateOpts,
|
|
12
|
-
Rotation,
|
|
13
|
-
} from './typings'
|
|
14
|
-
|
|
15
|
-
import { Easing, tweenProgress } from '../../shared-utils/animationFrame/tween'
|
|
16
|
-
|
|
17
|
-
const PI = Math.PI
|
|
18
|
-
const PI_2 = PI * 2
|
|
19
|
-
|
|
20
|
-
function formatLatitude(rad: number) {
|
|
21
|
-
return rad % PI_2
|
|
22
|
-
}
|
|
23
|
-
function formatLongitude(rad: number) {
|
|
24
|
-
return rad % PI_2
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const getLongitudeParams = (from: number, to: number, rotation: Rotation): { from: number; to: number } => {
|
|
28
|
-
from = formatLongitude(from)
|
|
29
|
-
to = formatLongitude(to)
|
|
30
|
-
|
|
31
|
-
// 逆时针旋转,初始值必须是较大的值
|
|
32
|
-
if (rotation === Rotation.Anticlockwise && from > to) to += PI_2
|
|
33
|
-
|
|
34
|
-
// 顺时针旋转,结束值必须是较大值
|
|
35
|
-
else if (rotation === Rotation.Clockwise && to > from) from += PI_2
|
|
36
|
-
|
|
37
|
-
// Loop 旋转,找锐角旋转
|
|
38
|
-
// 如果 to 比 from 大 180°,逆时针转
|
|
39
|
-
// 如果 from 比 to 大 180°,顺时针转
|
|
40
|
-
else if (rotation !== Rotation.Anticlockwise && rotation !== Rotation.Clockwise && to - from > PI) return getLongitudeParams(from, to, Rotation.Clockwise)
|
|
41
|
-
else if (rotation !== Rotation.Anticlockwise && rotation !== Rotation.Clockwise && from - to > PI) return getLongitudeParams(from, to, Rotation.Anticlockwise)
|
|
42
|
-
return { from, to }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function progressNumber(from: number, to: number, pst: number) {
|
|
46
|
-
return from + (to - from) * pst
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* **运镜插件** 模拟类似于电影运镜效果。
|
|
51
|
-
*/
|
|
52
|
-
export const CameraMovementPlugin: FivePlugin<CameraMovementPluginParameterType, CameraMovementPluginExportType> = (
|
|
53
|
-
five: Five,
|
|
54
|
-
) => {
|
|
55
|
-
|
|
56
|
-
const move = (args: Partial<MoveArgs>, duration: number, opts: MoveOpts = { preload: true }) => {
|
|
57
|
-
return new Promise<boolean>(async (resolve, reject) => {
|
|
58
|
-
|
|
59
|
-
if (opts.asyncStartCallback) {
|
|
60
|
-
opts.asyncStartCallback()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (five.panoIndex === undefined) {
|
|
64
|
-
return reject(false)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (args.mode && args.mode !== five.currentMode) {
|
|
68
|
-
await new Promise((resolve) => {
|
|
69
|
-
if (!args.mode) return
|
|
70
|
-
five.once('modeChange', (mode) => {
|
|
71
|
-
five.once('initAnimationEnded', () => {
|
|
72
|
-
if (mode === args.mode) {
|
|
73
|
-
resolve(true)
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
five.changeMode(args.mode, {
|
|
78
|
-
fov: args.fov || undefined,
|
|
79
|
-
latitude: args.latitude || undefined,
|
|
80
|
-
longitude: args.longitude || undefined,
|
|
81
|
-
panoIndex: args.panoIndex || undefined,
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (args.mode === Five.Mode.Floorplan) {
|
|
87
|
-
return resolve(true)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (opts.preload && args.panoIndex !== undefined && args.panoIndex !== five.panoIndex) {
|
|
91
|
-
await five.preloadPano(args.panoIndex)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (opts.asyncEndCallback) {
|
|
95
|
-
opts.asyncEndCallback()
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
args.panoIndex === undefined &&
|
|
100
|
-
args.fov === undefined &&
|
|
101
|
-
args.latitude === undefined &&
|
|
102
|
-
args.longitude === undefined
|
|
103
|
-
) {
|
|
104
|
-
return resolve(true)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const panoIndex = args.panoIndex !== undefined ? args.panoIndex : five.panoIndex
|
|
109
|
-
|
|
110
|
-
if (panoIndex !== undefined) {
|
|
111
|
-
const movePanoOptions: MovePanoOptions = Object.assign(args, {
|
|
112
|
-
duration, // 移动耗时
|
|
113
|
-
moveEndCallback: () => resolve(true), // 移动结束
|
|
114
|
-
moveCancelCallback: () => {
|
|
115
|
-
resolve(true)
|
|
116
|
-
}, // 移动开始
|
|
117
|
-
// effect: args.transEffect || 'fade',
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
await five.moveToPano(
|
|
121
|
-
panoIndex,
|
|
122
|
-
movePanoOptions,
|
|
123
|
-
)
|
|
124
|
-
} else {
|
|
125
|
-
reject(false)
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const getAnimeParams = (args: RotateArgs) => {
|
|
131
|
-
const currentFiveState = five.state
|
|
132
|
-
// latitude
|
|
133
|
-
const fromLatitude = formatLatitude(currentFiveState.latitude)
|
|
134
|
-
const toLatitude = formatLatitude(args.latitude)
|
|
135
|
-
// longitude
|
|
136
|
-
const { from: fromLongitude, to: toLongitude } = getLongitudeParams(
|
|
137
|
-
currentFiveState.longitude,
|
|
138
|
-
args.longitude,
|
|
139
|
-
args.rotation || Rotation.Loop,
|
|
140
|
-
)
|
|
141
|
-
// fov
|
|
142
|
-
const fromFov = currentFiveState.fov
|
|
143
|
-
const toFov = args.fov
|
|
144
|
-
return {
|
|
145
|
-
from: { latitude: fromLatitude, longitude: fromLongitude, fov: fromFov },
|
|
146
|
-
to: { latitude: toLatitude, longitude: toLongitude, fov: toFov },
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const rotate = async (args: RotateArgs, duration: number, opts: RotateOpts = {}) => {
|
|
151
|
-
if (opts.asyncStartCallback) {
|
|
152
|
-
opts.asyncStartCallback()
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// 先切换模型再出旋转效果
|
|
156
|
-
if (args.mode && five.currentMode !== args.mode) {
|
|
157
|
-
await five.changeMode(args.mode)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// 全景状态下,需要点位对齐
|
|
161
|
-
if (args.mode === Five.Mode.Panorama &&
|
|
162
|
-
five.currentMode === Five.Mode.Panorama &&
|
|
163
|
-
args.panoIndex !== undefined &&
|
|
164
|
-
args.panoIndex !== five.panoIndex) {
|
|
165
|
-
if (opts.preload) await five.preloadPano(args.panoIndex)
|
|
166
|
-
await new Promise((resolve, reject) => {
|
|
167
|
-
five.moveToPano(args.panoIndex, {
|
|
168
|
-
moveEndCallback: () => resolve(true), // 移动结束
|
|
169
|
-
moveCancelCallback: () => reject(false), // 移动开始
|
|
170
|
-
effect: 'fade',
|
|
171
|
-
})
|
|
172
|
-
})
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (opts.asyncEndCallback) {
|
|
176
|
-
opts.asyncEndCallback()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const { from, to } = getAnimeParams(args)
|
|
180
|
-
return await new Promise<boolean>((resolve, reject) => {
|
|
181
|
-
const onUpdate = ({ progress }: { progress: number }) => {
|
|
182
|
-
const state: Record<string, number> = {}
|
|
183
|
-
state.longitude = progressNumber(from.longitude, to.longitude, progress) % PI_2
|
|
184
|
-
state.latitude = progressNumber(from.latitude, to.latitude, progress)
|
|
185
|
-
state.fov = progressNumber(from.fov, to.fov, progress)
|
|
186
|
-
five.setState(state, true)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const onComplete = () => {
|
|
190
|
-
resolve(true)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const onDestroy = () => {
|
|
194
|
-
resolve(false)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
let animeDuration = duration
|
|
198
|
-
|
|
199
|
-
if (args.rotation === Rotation.Loop) {
|
|
200
|
-
animeDuration = args.rotateSpeed
|
|
201
|
-
? Math.ceil((Math.abs(to.longitude - from.longitude) / args.rotateSpeed) * 1000)
|
|
202
|
-
: duration
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
type _Tween = TWEEN.Tween<{ progress: number }> & { onDestroy: (p: any) => _Tween; destroy: () => void }
|
|
206
|
-
|
|
207
|
-
const tween = (tweenProgress(animeDuration, Easing.Linear.None) as _Tween)
|
|
208
|
-
.onUpdate(onUpdate)
|
|
209
|
-
.onComplete(onComplete)
|
|
210
|
-
.onDestroy(onDestroy)
|
|
211
|
-
if (args.rotation === Rotation.Loop) {
|
|
212
|
-
tween.repeat(Infinity).yoyo(true)
|
|
213
|
-
}
|
|
214
|
-
setTimeout(() => {
|
|
215
|
-
// 总时间到了之后强制结束,同时也是 Loop 模式的结束方式
|
|
216
|
-
tween.destroy()
|
|
217
|
-
resolve(true)
|
|
218
|
-
}, duration)
|
|
219
|
-
})
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
move,
|
|
224
|
-
rotate,
|
|
225
|
-
}
|
|
226
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier */
|
|
2
|
-
import { Mode, MovePanoOptions, Pose } from '@realsee/five'
|
|
3
|
-
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
5
|
-
export interface CameraMovementPluginParameterType { }
|
|
6
|
-
|
|
7
|
-
export interface CameraMovementPluginExportType {
|
|
8
|
-
/**
|
|
9
|
-
* 运镜:移动
|
|
10
|
-
* @param moveArgs
|
|
11
|
-
* @param duration
|
|
12
|
-
* @param opts
|
|
13
|
-
*/
|
|
14
|
-
move(moveArgs: Partial<MoveArgs>, duration: number, opts?: MoveOpts): Promise<boolean>
|
|
15
|
-
/**
|
|
16
|
-
* 运镜:旋转
|
|
17
|
-
* @param args
|
|
18
|
-
* @param duration
|
|
19
|
-
* @param opts
|
|
20
|
-
*/
|
|
21
|
-
rotate(args: RotateArgs, duration: number, opts?: RotateOpts): Promise<boolean>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export enum CameraMovementEffect {
|
|
25
|
-
Move = 'Move',
|
|
26
|
-
Rotate = 'Rotate',
|
|
27
|
-
}
|
|
28
|
-
export enum Rotation {
|
|
29
|
-
Clockwise = 'Clockwise',
|
|
30
|
-
Anticlockwise = 'Anticlockwise',
|
|
31
|
-
Loop = 'Loop',
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface CameraMovementOptsCallback {
|
|
35
|
-
asyncStartCallback?: () => void
|
|
36
|
-
asyncEndCallback?: () => void
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type MoveArgs = {
|
|
40
|
-
mode: Mode
|
|
41
|
-
panoIndex: number
|
|
42
|
-
transEffect?: "fly" | "fade" | "instant"
|
|
43
|
-
} & Pose
|
|
44
|
-
|
|
45
|
-
export type MoveOpts = {
|
|
46
|
-
preload?: boolean
|
|
47
|
-
} & CameraMovementOptsCallback
|
|
48
|
-
|
|
49
|
-
export type RotateArgs = {
|
|
50
|
-
mode?: Mode
|
|
51
|
-
panoIndex: number
|
|
52
|
-
loop: boolean
|
|
53
|
-
rotateSpeed: number
|
|
54
|
-
rotation: Rotation
|
|
55
|
-
} & Pose
|
|
56
|
-
|
|
57
|
-
export type RotateOpts = {
|
|
58
|
-
preload?: boolean
|
|
59
|
-
} & CameraMovementOptsCallback
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import * as THREE from 'three'
|
|
2
|
-
import type { FivePlugin } from '@realsee/five'
|
|
3
|
-
|
|
4
|
-
export interface ModelTVVideoPluginData {
|
|
5
|
-
enable?: boolean
|
|
6
|
-
video_src: string
|
|
7
|
-
video_poster_src: string
|
|
8
|
-
points: { x: number; y: number; z: number }[][]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ModelTVVideoPluginParameterType {
|
|
12
|
-
videoElement?: HTMLVideoElement
|
|
13
|
-
}
|
|
14
|
-
export interface ModelTVVideoPluginExportType {
|
|
15
|
-
enable: () => void
|
|
16
|
-
disable: () => void
|
|
17
|
-
load: (data: ModelTVVideoPluginData, videoElement?: HTMLVideoElement) => Promise<void>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type ModelTVVideoPluginPoints = THREE.Vector3[][]
|
|
21
|
-
|
|
22
|
-
type ModelTVVideoPluginState = {
|
|
23
|
-
videoMeshes: THREE.Mesh<THREE.BufferGeometry, THREE.MeshBasicMaterial>[]
|
|
24
|
-
videoTextureEnabled: boolean
|
|
25
|
-
videoSource: string
|
|
26
|
-
rectPoints: ModelTVVideoPluginPoints
|
|
27
|
-
enabled: boolean
|
|
28
|
-
imageTexture?: THREE.Texture
|
|
29
|
-
videoTexture?: THREE.VideoTexture
|
|
30
|
-
videoElement?: HTMLVideoElement
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const ModelTVVideoPlugin: FivePlugin<ModelTVVideoPluginParameterType, ModelTVVideoPluginExportType> = (
|
|
34
|
-
five,
|
|
35
|
-
{ videoElement },
|
|
36
|
-
) => {
|
|
37
|
-
const state: ModelTVVideoPluginState = {
|
|
38
|
-
videoMeshes: [],
|
|
39
|
-
videoTextureEnabled: false,
|
|
40
|
-
videoSource: '',
|
|
41
|
-
rectPoints: [],
|
|
42
|
-
enabled: false,
|
|
43
|
-
videoElement: videoElement,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const setMuted = (muted: boolean) => {
|
|
47
|
-
if (state.videoTexture) {
|
|
48
|
-
state.videoTexture.image.muted = muted
|
|
49
|
-
state.videoTexture.image.play()
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const getMuted = () => {
|
|
53
|
-
if (state.videoTexture) return state.videoTexture.image.muted
|
|
54
|
-
else return true
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const enable = () => {
|
|
58
|
-
if (state.enabled) return
|
|
59
|
-
if (!state.videoTexture) return
|
|
60
|
-
|
|
61
|
-
state.enabled = true
|
|
62
|
-
state.videoMeshes = createPanoVideoMeshes()
|
|
63
|
-
state.videoMeshes.forEach((mesh) => five.scene.add(mesh))
|
|
64
|
-
|
|
65
|
-
const play = () => {
|
|
66
|
-
if (!state.videoTexture) return
|
|
67
|
-
|
|
68
|
-
const timeupdate = () => {
|
|
69
|
-
if (!state.videoTexture) return
|
|
70
|
-
state.videoTexture?.image.removeEventListener('timeupdate', timeupdate)
|
|
71
|
-
state.videoTextureEnabled = true
|
|
72
|
-
state.videoMeshes.forEach((mesh) => {
|
|
73
|
-
if (mesh.material.map !== state.videoTexture) mesh.material.map = state.videoTexture!
|
|
74
|
-
})
|
|
75
|
-
five.needsRender = true
|
|
76
|
-
}
|
|
77
|
-
state.videoTexture.image.addEventListener('timeupdate', timeupdate)
|
|
78
|
-
if (state.videoTexture && state.videoMeshes.length) {
|
|
79
|
-
state.videoTexture.image.play()
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (five.model.loaded) play()
|
|
84
|
-
else {
|
|
85
|
-
return five.once('modelLoaded', () => play())
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const disable = () => {
|
|
90
|
-
if (!state.enabled) return
|
|
91
|
-
state.enabled = false
|
|
92
|
-
state.videoMeshes.forEach((mesh) => {
|
|
93
|
-
mesh.geometry.dispose()
|
|
94
|
-
mesh.material.dispose()
|
|
95
|
-
five.scene.remove(mesh)
|
|
96
|
-
if (state.videoTexture) state.videoTexture.image.pause()
|
|
97
|
-
})
|
|
98
|
-
state.videoMeshes = []
|
|
99
|
-
five.needsRender = true
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const createPanoVideoMeshes = () => {
|
|
103
|
-
return state.rectPoints.map((points, index) => {
|
|
104
|
-
const geometry = new THREE.BufferGeometry()
|
|
105
|
-
const segments = 128
|
|
106
|
-
|
|
107
|
-
const verticesArray: number[] = []
|
|
108
|
-
verticesArray.push(points[0].x, points[0].y, points[0].z)
|
|
109
|
-
for (let i = 1; i < segments; i++) {
|
|
110
|
-
verticesArray.push(
|
|
111
|
-
points[0].x + ((points[1].x - points[0].x) * i) / segments,
|
|
112
|
-
points[0].y + ((points[1].y - points[0].y) * i) / segments,
|
|
113
|
-
points[0].z + ((points[1].z - points[0].z) * i) / segments,
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
verticesArray.push(points[1].x, points[1].y, points[1].z)
|
|
117
|
-
verticesArray.push(points[2].x, points[2].y, points[2].z)
|
|
118
|
-
for (let i = 1; i < segments; i++) {
|
|
119
|
-
verticesArray.push(
|
|
120
|
-
points[2].x + ((points[3].x - points[2].x) * i) / segments,
|
|
121
|
-
points[2].y + ((points[3].y - points[2].y) * i) / segments,
|
|
122
|
-
points[2].z + ((points[3].z - points[2].z) * i) / segments,
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
verticesArray.push(points[3].x, points[3].y, points[3].z)
|
|
126
|
-
|
|
127
|
-
const uvArray: number[] = []
|
|
128
|
-
uvArray.push(0, 1)
|
|
129
|
-
for (let i = 1; i < segments; i++) {
|
|
130
|
-
uvArray.push(0, 1 - i / segments)
|
|
131
|
-
}
|
|
132
|
-
uvArray.push(0, 0)
|
|
133
|
-
uvArray.push(1, 0)
|
|
134
|
-
for (let i = 1; i < segments; i++) {
|
|
135
|
-
uvArray.push(1, i / segments)
|
|
136
|
-
}
|
|
137
|
-
uvArray.push(1, 1)
|
|
138
|
-
|
|
139
|
-
const indicesArray: number[] = []
|
|
140
|
-
for (let i = 0; i < segments; i++) {
|
|
141
|
-
indicesArray.push(i, i + 1, segments * 2 - i, i, segments * 2 - i, segments * 2 + 1 - i)
|
|
142
|
-
}
|
|
143
|
-
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticesArray), 3))
|
|
144
|
-
geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvArray), 2))
|
|
145
|
-
geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indicesArray), 1))
|
|
146
|
-
const material = new THREE.MeshBasicMaterial({
|
|
147
|
-
map: state.videoTextureEnabled ? state.videoTexture : state.imageTexture,
|
|
148
|
-
side: THREE.DoubleSide,
|
|
149
|
-
})
|
|
150
|
-
const mesh = new THREE.Mesh(geometry, material)
|
|
151
|
-
mesh.renderOrder = 1
|
|
152
|
-
mesh.name = `video-${index}-${performance.now()}`
|
|
153
|
-
return mesh
|
|
154
|
-
})
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const getImageTexture = (source: string) => {
|
|
158
|
-
const texture = new THREE.TextureLoader().load(source)
|
|
159
|
-
texture.minFilter = THREE.LinearFilter
|
|
160
|
-
texture.magFilter = THREE.LinearFilter
|
|
161
|
-
texture.format = THREE.RGBFormat
|
|
162
|
-
return texture
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const getVideoTexture = (
|
|
166
|
-
source: string,
|
|
167
|
-
video?: HTMLVideoElement,
|
|
168
|
-
): Promise<THREE.VideoTexture & { videoSource: string }> => {
|
|
169
|
-
return new Promise((resolve, reject) => {
|
|
170
|
-
const xhr = new XMLHttpRequest()
|
|
171
|
-
xhr.onreadystatechange = () => {
|
|
172
|
-
if (xhr.readyState == 4) {
|
|
173
|
-
if (xhr.status == 200) {
|
|
174
|
-
const url = window.URL || window.webkitURL
|
|
175
|
-
video = video || document.createElement('video')
|
|
176
|
-
video.crossOrigin = 'anonymous'
|
|
177
|
-
video.autoplay = true
|
|
178
|
-
video.muted = true
|
|
179
|
-
video.loop = true
|
|
180
|
-
video.playsInline = true
|
|
181
|
-
video.src = url.createObjectURL(xhr.response)
|
|
182
|
-
const texture = new THREE.VideoTexture(video)
|
|
183
|
-
texture.minFilter = THREE.LinearFilter
|
|
184
|
-
texture.magFilter = THREE.LinearFilter
|
|
185
|
-
texture.format = THREE.RGBFormat
|
|
186
|
-
resolve(Object.assign(texture, { videoSource: source }))
|
|
187
|
-
} else {
|
|
188
|
-
reject(new Error('Video download Error: ' + xhr.status))
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
xhr.onerror = (error) => reject(error)
|
|
193
|
-
xhr.open('GET', source)
|
|
194
|
-
xhr.responseType = 'blob'
|
|
195
|
-
xhr.send()
|
|
196
|
-
})
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const load = async (data: ModelTVVideoPluginData, videoElement?: HTMLVideoElement) => {
|
|
200
|
-
const { video_src, video_poster_src, points } = data
|
|
201
|
-
state.videoSource = video_src
|
|
202
|
-
state.rectPoints = points.map((items) => items.map(({ x, y, z }) => new THREE.Vector3(x, y, z)))
|
|
203
|
-
state.imageTexture = getImageTexture(video_poster_src)
|
|
204
|
-
|
|
205
|
-
if (videoElement) {
|
|
206
|
-
state.videoElement = videoElement
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
state.videoTexture = await getVideoTexture(state.videoSource, state.videoElement)
|
|
210
|
-
|
|
211
|
-
state.enabled = !!data.enable
|
|
212
|
-
if (state.enabled) enable()
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
five.on('modeChange', () => setMuted(true))
|
|
216
|
-
|
|
217
|
-
five.on('wantsTapGesture', (raycaster) => {
|
|
218
|
-
if (!state.enabled) return
|
|
219
|
-
const [intersect] = raycaster.intersectObjects(five.scene.children, true)
|
|
220
|
-
if (!!intersect && /^video/.test(intersect.object.name)) {
|
|
221
|
-
if (state.videoTexture) setMuted(!state.videoTexture.image.muted)
|
|
222
|
-
return false
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
five.on('panoArrived', () => {
|
|
227
|
-
if (!state.enabled) return
|
|
228
|
-
if (getMuted()) return
|
|
229
|
-
const cameraPosition = five.camera.position
|
|
230
|
-
|
|
231
|
-
const visible = state.rectPoints.find((points) => {
|
|
232
|
-
const centerVector = points.reduce(
|
|
233
|
-
(total, curr) =>
|
|
234
|
-
new THREE.Vector3(
|
|
235
|
-
total.x + curr.x / points.length,
|
|
236
|
-
total.y + curr.y / points.length,
|
|
237
|
-
total.z + curr.z / points.length,
|
|
238
|
-
),
|
|
239
|
-
new THREE.Vector3(),
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
return (
|
|
243
|
-
points
|
|
244
|
-
.map(
|
|
245
|
-
(point) =>
|
|
246
|
-
new THREE.Vector3(
|
|
247
|
-
(point.x + centerVector.x) / 2,
|
|
248
|
-
(point.y + centerVector.y) / 2,
|
|
249
|
-
(point.z + centerVector.z) / 2,
|
|
250
|
-
),
|
|
251
|
-
)
|
|
252
|
-
.filter((vector) => {
|
|
253
|
-
vector = vector.clone().sub(cameraPosition).normalize()
|
|
254
|
-
const raycaster = new THREE.Raycaster(cameraPosition, vector)
|
|
255
|
-
const [intersect] = raycaster.intersectObjects(five.scene.children, true)
|
|
256
|
-
return !!intersect && /^video/.test(intersect.object.name)
|
|
257
|
-
}).length >= 2
|
|
258
|
-
)
|
|
259
|
-
})
|
|
260
|
-
if (!visible) setMuted(true)
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
five.on('renderFrame', () => {
|
|
264
|
-
state.videoMeshes.forEach((meshes) => {
|
|
265
|
-
if (meshes)
|
|
266
|
-
//@ts-ignore
|
|
267
|
-
meshes.needsRender = true
|
|
268
|
-
})
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
five.on('load', (input) => {
|
|
272
|
-
if (input.modelTVVideoData) {
|
|
273
|
-
load(input.modelTVVideoData)
|
|
274
|
-
}
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
return { enable, disable, load }
|
|
278
|
-
}
|
package/resources/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Player } from './Player'
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { unsafe__useFiveInstance } from '@realsee/five/react'
|
|
2
|
-
import * as React from 'react'
|
|
3
|
-
import { Player } from '../Player'
|
|
4
|
-
import { PlayerConfigs } from '../Player/typings'
|
|
5
|
-
import { VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
|
|
6
|
-
|
|
7
|
-
const VreoContext = React.createContext<Player | null>(null)
|
|
8
|
-
|
|
9
|
-
export interface VreoProviderProps {
|
|
10
|
-
configs?: Partial<PlayerConfigs>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const VreoProvider: React.FC<VreoProviderProps> = (props ) => {
|
|
14
|
-
const five = unsafe__useFiveInstance()
|
|
15
|
-
|
|
16
|
-
const [player, setPlayer] = React.useState<Player | null>(null)
|
|
17
|
-
const playerRef = React.useRef<Player | null>(null)
|
|
18
|
-
|
|
19
|
-
React.useEffect(() => {
|
|
20
|
-
playerRef.current = new Player(five, props.configs || {})
|
|
21
|
-
setPlayer(playerRef.current)
|
|
22
|
-
|
|
23
|
-
return () => {
|
|
24
|
-
playerRef.current?.dispose()
|
|
25
|
-
}
|
|
26
|
-
}, [])
|
|
27
|
-
|
|
28
|
-
if (!player) return <></>
|
|
29
|
-
|
|
30
|
-
return <VreoContext.Provider value={player}>{props.children}</VreoContext.Provider>
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function useVreoInstance() {
|
|
34
|
-
const context = React.useContext(VreoContext)
|
|
35
|
-
if (!context) {
|
|
36
|
-
throw new Error('VreoProvider never found.')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return context
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* VreoPlayer 命令集合。
|
|
44
|
-
*/
|
|
45
|
-
export interface VreoActionCallbacks {
|
|
46
|
-
/**
|
|
47
|
-
* 载入剧本数据。
|
|
48
|
-
* @param vreoUnit 剧本数据
|
|
49
|
-
* @param currentTime 开始时间戳
|
|
50
|
-
* @param preload 是否开启预载
|
|
51
|
-
* @param force 是否强制载入
|
|
52
|
-
*/
|
|
53
|
-
load: (vreoUnit: VreoUnit, currentTime?: number, preload?: boolean, force?: boolean) => Promise<boolean>
|
|
54
|
-
/**
|
|
55
|
-
* 播放。
|
|
56
|
-
*/
|
|
57
|
-
play: (currentTime?: number) => void
|
|
58
|
-
/**
|
|
59
|
-
* 暂停。
|
|
60
|
-
*/
|
|
61
|
-
pause: () => void
|
|
62
|
-
/**
|
|
63
|
-
* 显示 UI 面板。
|
|
64
|
-
*/
|
|
65
|
-
show: () => void
|
|
66
|
-
/**
|
|
67
|
-
* 隐藏 UI 面板。
|
|
68
|
-
*/
|
|
69
|
-
hide: () => void
|
|
70
|
-
/**
|
|
71
|
-
* 销毁数据及部分定时任务。
|
|
72
|
-
*/
|
|
73
|
-
dispose: () => void
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function useVreoAction() {
|
|
77
|
-
const player = useVreoInstance()
|
|
78
|
-
|
|
79
|
-
const load = React.useCallback(
|
|
80
|
-
(vreoUnit: VreoUnit, currentTime?: number) => player.load(vreoUnit, currentTime),
|
|
81
|
-
[player]
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
const play = React.useCallback((currentTime?: number) => player.play(currentTime || 0), [player])
|
|
85
|
-
const pause = React.useCallback(() => player.pause(), [player])
|
|
86
|
-
const show = React.useCallback(() => player.show(), [player])
|
|
87
|
-
const hide = React.useCallback(() => player.hide(), [player])
|
|
88
|
-
const dispose = React.useCallback(() => player.dispose(), [player])
|
|
89
|
-
|
|
90
|
-
return { load, pause, show, play, hide, dispose }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function useVreoEventCallback<T extends keyof VreoKeyframeEvent>(
|
|
94
|
-
name: T,
|
|
95
|
-
callback: VreoKeyframeEvent[T],
|
|
96
|
-
deps?: React.DependencyList | undefined
|
|
97
|
-
) {
|
|
98
|
-
const player = useVreoInstance()
|
|
99
|
-
let dependencyList: React.DependencyList = [player, name]
|
|
100
|
-
if (deps !== undefined) {
|
|
101
|
-
dependencyList = dependencyList.concat(deps)
|
|
102
|
-
}
|
|
103
|
-
React.useEffect(() => {
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
player.on(name, callback)
|
|
106
|
-
return () => {
|
|
107
|
-
// @ts-ignore
|
|
108
|
-
player.off(name, callback)
|
|
109
|
-
}
|
|
110
|
-
}, dependencyList)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function useVreoPausedState() {
|
|
114
|
-
const player = useVreoInstance()
|
|
115
|
-
const [state, setState] = React.useState(player.paused)
|
|
116
|
-
|
|
117
|
-
useVreoEventCallback('paused', () => setState(true))
|
|
118
|
-
useVreoEventCallback('playing', () => setState(false))
|
|
119
|
-
|
|
120
|
-
return state
|
|
121
|
-
}
|