@realsee/vreo 0.1.6-alpha.5 → 0.2.0-alpha.2
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 +36 -13
- package/docs/assets/custom.css +2 -2
- package/docs/assets/search.js +1 -1
- package/docs/classes/Player.Controller.html +54 -0
- package/docs/classes/Player.Player-1.html +11 -11
- package/docs/classes/Player.VideoAgentMesh.html +142 -0
- package/docs/classes/Player.VideoAgentScene.html +1 -0
- package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
- package/docs/enums/Player.PanoEffectEnum.html +2 -2
- package/docs/enums/Player.PanoTagEnum.html +1 -1
- package/docs/enums/Player.VreoKeyframeEnum.html +14 -12
- package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
- package/docs/enums/fivePlugins.Rotation.html +1 -1
- package/docs/index.html +25 -16
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -0
- package/docs/interfaces/Player.PlayerConfigs.html +4 -2
- package/docs/interfaces/Player.Vertex.html +1 -1
- package/docs/interfaces/Player.VideoAgentMeshOptions.html +1 -0
- package/docs/interfaces/Player.VreoKeyframe.html +1 -1
- package/docs/interfaces/Player.VreoUnit.html +1 -1
- package/docs/interfaces/Player.VreoVideo.html +1 -1
- package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +1 -1
- package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +3 -3
- package/docs/interfaces/fivePlugins.CameraMovementPluginParameterType.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +1 -1
- package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +1 -1
- package/docs/interfaces/react.VreoActionCallbacks.html +7 -7
- package/docs/interfaces/react.VreoProviderProps.html +1 -0
- package/docs/modules/Player.html +13 -13
- package/docs/modules/custom.html +3 -0
- package/docs/modules/fivePlugins.html +2 -2
- package/docs/modules/react.html +1 -1
- package/docs/modules.html +1 -1
- package/lib/Player/App.js +6 -2
- package/lib/Player/custom/SpatialScenePanel/index.d.ts +22 -0
- package/lib/Player/custom/SpatialScenePanel/index.js +207 -0
- package/lib/Player/index.js +27 -8
- package/lib/Player/modules/Drawer/index.js +1 -1
- package/lib/Player/modules/keyframes/BgMusic/index.d.ts +2 -0
- package/lib/Player/modules/keyframes/BgMusic/index.js +76 -0
- package/lib/Player/modules/keyframes/InfoPanel/index.js +52 -8
- package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +55 -16
- package/lib/Player/typings.d.ts +13 -1
- package/lib/react/index.d.ts +5 -1
- package/lib/react/index.js +1 -1
- package/lib/typings/VreoUnit.d.ts +32 -4
- package/lib/typings/VreoUnit.js +1 -0
- package/package.json +4 -3
- package/resources/Player/App.tsx +4 -1
- package/resources/Player/custom/SpatialScenePanel/index.tsx +161 -0
- package/resources/Player/index.tsx +16 -1
- package/resources/Player/modules/Drawer/index.tsx +1 -1
- package/resources/Player/modules/keyframes/BgMusic/index.tsx +66 -0
- package/resources/Player/modules/keyframes/InfoPanel/index.tsx +59 -6
- package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +63 -15
- package/resources/Player/typings.ts +16 -1
- package/resources/react/index.tsx +7 -2
- package/resources/typings/VreoUnit.ts +40 -4
- package/stylesheets/custom/SpatialScenePanel.css +303 -0
- package/stylesheets/default.css +46 -2
|
@@ -18,27 +18,47 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
|
|
|
18
18
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
19
19
|
|
|
20
20
|
function InfoPanelImg(_ref) {
|
|
21
|
-
var url = _ref.url
|
|
21
|
+
var url = _ref.url,
|
|
22
|
+
children = _ref.children;
|
|
22
23
|
return /*#__PURE__*/React.createElement("div", {
|
|
23
24
|
className: "vreo-infoPanel vreo-infoPanel--img"
|
|
24
|
-
}, /*#__PURE__*/React.createElement("
|
|
25
|
+
}, children, /*#__PURE__*/React.createElement("div", {
|
|
25
26
|
className: "vreo-infoPanelImg",
|
|
26
|
-
|
|
27
|
+
style: {
|
|
28
|
+
backgroundImage: "url(".concat(url, ")")
|
|
29
|
+
}
|
|
27
30
|
}));
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
function InfoPanelVideo(_ref2) {
|
|
31
|
-
var url = _ref2.url
|
|
34
|
+
var url = _ref2.url,
|
|
35
|
+
children = _ref2.children;
|
|
32
36
|
return /*#__PURE__*/React.createElement("div", {
|
|
33
37
|
className: "vreo-infoPanel vreo-infoPanel--video"
|
|
38
|
+
}, children, /*#__PURE__*/React.createElement("div", {
|
|
39
|
+
className: "vreo-infoPanelWrapper"
|
|
34
40
|
}, /*#__PURE__*/React.createElement("video", {
|
|
35
41
|
playsInline: true,
|
|
36
42
|
autoPlay: true,
|
|
37
43
|
className: "vreo-infoPanelVideo",
|
|
38
44
|
src: url
|
|
39
|
-
}));
|
|
45
|
+
})));
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
var Title = function Title(props) {
|
|
49
|
+
if (!props.title && !props.subTitle) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
54
|
+
className: "vreo-infoPanel-title"
|
|
55
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
56
|
+
className: "vreo-infoPanel-t1"
|
|
57
|
+
}, props.title), /*#__PURE__*/React.createElement("div", {
|
|
58
|
+
className: "vreo-infoPanel-t2"
|
|
59
|
+
}, props.subTitle));
|
|
60
|
+
};
|
|
61
|
+
|
|
42
62
|
function InfoPanel() {
|
|
43
63
|
var timeoutRef = React.useRef();
|
|
44
64
|
var controller = (0, _hooks.useController)();
|
|
@@ -54,19 +74,27 @@ function InfoPanel() {
|
|
|
54
74
|
end = keyframe.end,
|
|
55
75
|
data = keyframe.data;
|
|
56
76
|
var infoPanelData = data;
|
|
77
|
+
var title = infoPanelData.title,
|
|
78
|
+
subTitle = infoPanelData.subTitle;
|
|
57
79
|
|
|
58
80
|
if (infoPanelData.type === _VreoUnit.InfoPanelTypeEnum.Image) {
|
|
59
81
|
controller.openDrawer({
|
|
60
82
|
content: /*#__PURE__*/React.createElement(InfoPanelImg, {
|
|
61
83
|
url: infoPanelData.url
|
|
62
|
-
}
|
|
84
|
+
}, /*#__PURE__*/React.createElement(Title, {
|
|
85
|
+
title: title,
|
|
86
|
+
subTitle: subTitle
|
|
87
|
+
})),
|
|
63
88
|
height: '60vh'
|
|
64
89
|
});
|
|
65
90
|
} else if (infoPanelData.type === _VreoUnit.InfoPanelTypeEnum.Video) {
|
|
66
91
|
controller.openDrawer({
|
|
67
92
|
content: /*#__PURE__*/React.createElement(InfoPanelVideo, {
|
|
68
93
|
url: infoPanelData.url
|
|
69
|
-
}
|
|
94
|
+
}, /*#__PURE__*/React.createElement(Title, {
|
|
95
|
+
title: title,
|
|
96
|
+
subTitle: subTitle
|
|
97
|
+
})),
|
|
70
98
|
height: '60vh'
|
|
71
99
|
});
|
|
72
100
|
}
|
|
@@ -76,7 +104,23 @@ function InfoPanel() {
|
|
|
76
104
|
}, end - start);
|
|
77
105
|
};
|
|
78
106
|
|
|
79
|
-
controller.on(_VreoUnit.VreoKeyframeEnum.InfoPanel, callback);
|
|
107
|
+
controller.on(_VreoUnit.VreoKeyframeEnum.InfoPanel, callback); // Object.assign(window, {
|
|
108
|
+
// $setInfoPanel: () => {
|
|
109
|
+
// controller.openDrawer({
|
|
110
|
+
// content: (
|
|
111
|
+
// // <InfoPanelImg url='//vrlab-public.ljcdn.com/release/seesay/tools/cat_music___f68fb9bbe1f7cd6d00a16456dd0b09ad.gif'>
|
|
112
|
+
// // <InfoPanelImg url="http://vrlab-public.ljcdn.com/common/images/web/d94e1bd7-0311-4b20-9c41-a1294fe43554.png">
|
|
113
|
+
// // <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
114
|
+
// // </InfoPanelImg>
|
|
115
|
+
// <InfoPanelVideo url="//vrlab-public.ljcdn.com/release/seesay/tools/2022011713142___b320f74a5e1b5ad4bb46b4dc69d73ecc.mp4">
|
|
116
|
+
// <Title title="场景联动抓拍图片" subTitle={'2022.02.17 14:00'} />
|
|
117
|
+
// </InfoPanelVideo>
|
|
118
|
+
// ),
|
|
119
|
+
// height: '60vh',
|
|
120
|
+
// })
|
|
121
|
+
// },
|
|
122
|
+
// })
|
|
123
|
+
|
|
80
124
|
return function () {
|
|
81
125
|
controller.off(_VreoUnit.VreoKeyframeEnum.InfoPanel, callback);
|
|
82
126
|
|
|
@@ -22,37 +22,76 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
22
22
|
function UpdateVRPanorama() {
|
|
23
23
|
var controller = (0, _hooks.useController)();
|
|
24
24
|
var five = (0, _hooks.useFiveInstance)();
|
|
25
|
+
var rawRef = React.useRef(null);
|
|
26
|
+
var workRef = React.useRef(null);
|
|
27
|
+
var restoreCallback = React.useCallback(function () {
|
|
28
|
+
if (rawRef.current) {
|
|
29
|
+
var work = (0, _five.parseWork)(rawRef.current);
|
|
30
|
+
five.load(work);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
workRef.current = null;
|
|
34
|
+
}, []);
|
|
35
|
+
var pausedCallback = React.useCallback(function () {
|
|
36
|
+
if (rawRef.current) {
|
|
37
|
+
var work = (0, _five.parseWork)(rawRef.current);
|
|
38
|
+
five.load(work);
|
|
39
|
+
}
|
|
40
|
+
}, []);
|
|
41
|
+
var playingCallback = React.useCallback(function () {
|
|
42
|
+
if (!workRef.current) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
five.load(workRef.current);
|
|
47
|
+
}, []);
|
|
25
48
|
React.useEffect(function () {
|
|
26
49
|
var callback = function callback(keyframe) {
|
|
27
50
|
var _five$work;
|
|
28
51
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
52
|
+
if (!rawRef.current) {
|
|
53
|
+
rawRef.current = five.work.raw.works;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var data = keyframe.data; // 如果数据中有新 work 数据,则直接载入
|
|
33
57
|
|
|
34
|
-
if (work) {
|
|
35
|
-
|
|
58
|
+
if (data.work) {
|
|
59
|
+
workRef.current = (0, _five.parseWork)(data.work);
|
|
60
|
+
five.load(workRef.current);
|
|
36
61
|
return;
|
|
37
62
|
}
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
var newWorkJSON = JSON.parse(JSON.stringify((_five$work = five.work) === null || _five$work === void 0 ? void 0 : _five$work.raw.work)); // // 原Work数据不能被修改
|
|
64
|
+
var lastRawWork = (_five$work = five.work) === null || _five$work === void 0 ? void 0 : _five$work.raw.works[0]; // 动态场景:不提供完成的签名数据,需重新整理
|
|
41
65
|
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
66
|
+
if (data.dynamic_scene && !data.panorama) {
|
|
67
|
+
var lastWork = JSON.parse(lastRawWork);
|
|
68
|
+
var panorama = lastWork.panorama;
|
|
69
|
+
var index = data.dynamic_scene.images.index;
|
|
70
|
+
panorama.list[index] = data.dynamic_scene.images;
|
|
71
|
+
data.panorama = panorama;
|
|
72
|
+
delete data.dynamic_scene;
|
|
46
73
|
}
|
|
47
74
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
five.load(newWork);
|
|
75
|
+
workRef.current = (0, _five.parseWork)([lastRawWork, data]);
|
|
76
|
+
five.load(workRef.current);
|
|
51
77
|
};
|
|
52
78
|
|
|
53
|
-
controller.on(_VreoUnit.VreoKeyframeEnum.UpdateVRPanorama, callback);
|
|
79
|
+
controller.on(_VreoUnit.VreoKeyframeEnum.UpdateVRPanorama, callback); // 离开 将之前的内容清空
|
|
80
|
+
|
|
81
|
+
controller.on(_VreoUnit.VreoKeyframeEnum.Exit, restoreCallback); // 新载入数据 将之前的内容清空
|
|
82
|
+
|
|
83
|
+
controller.on('loaded', restoreCallback); // 暂停 回到默认状态
|
|
84
|
+
|
|
85
|
+
controller.on('paused', pausedCallback); // 播放 回归暂停前状态
|
|
86
|
+
|
|
87
|
+
controller.on('playing', playingCallback);
|
|
54
88
|
return function () {
|
|
89
|
+
// 清理事件监听
|
|
55
90
|
controller.off(_VreoUnit.VreoKeyframeEnum.UpdateVRPanorama, callback);
|
|
91
|
+
controller.off(_VreoUnit.VreoKeyframeEnum.Exit, restoreCallback);
|
|
92
|
+
controller.off('loaded', restoreCallback);
|
|
93
|
+
controller.off('paused', pausedCallback);
|
|
94
|
+
controller.off('playing', playingCallback);
|
|
56
95
|
};
|
|
57
96
|
}, [controller]);
|
|
58
97
|
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
package/lib/Player/typings.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Subscribe, Five } from '@realsee/five';
|
|
3
|
+
import { VreoKeyframeConfigMap, VreoKeyframeEvent } from '../typings/VreoUnit';
|
|
2
4
|
export interface PlayerConfigs {
|
|
3
5
|
containter?: ReactDOM.Container;
|
|
4
6
|
keyframeMap: VreoKeyframeConfigMap;
|
|
@@ -11,4 +13,14 @@ export interface PlayerConfigs {
|
|
|
11
13
|
videoEffect?: HTMLVideoElement;
|
|
12
14
|
modelTVVideo?: HTMLVideoElement;
|
|
13
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* 如果需要在 底部面板添加自定义内容,可以传递个 React 组件。
|
|
18
|
+
*/
|
|
19
|
+
customPanelChildren?: ReactNode;
|
|
20
|
+
customKeyframes?: React.FC<CustomVreoKeyframeProps>[];
|
|
21
|
+
}
|
|
22
|
+
export declare type VreoSubscribe = Pick<Subscribe<VreoKeyframeEvent>, 'on' | 'once' | 'off'>;
|
|
23
|
+
export interface CustomVreoKeyframeProps {
|
|
24
|
+
subscribe: VreoSubscribe;
|
|
25
|
+
five: Five;
|
|
14
26
|
}
|
package/lib/react/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { PlayerConfigs } from '../Player/typings';
|
|
2
3
|
import { VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit';
|
|
3
|
-
export
|
|
4
|
+
export interface VreoProviderProps {
|
|
5
|
+
configs?: Partial<PlayerConfigs>;
|
|
6
|
+
}
|
|
7
|
+
export declare const VreoProvider: React.FC<VreoProviderProps>;
|
|
4
8
|
/**
|
|
5
9
|
* VreoPlayer 命令集合。
|
|
6
10
|
*/
|
package/lib/react/index.js
CHANGED
|
@@ -44,7 +44,7 @@ var VreoProvider = function VreoProvider(props) {
|
|
|
44
44
|
|
|
45
45
|
var playerRef = React.useRef(null);
|
|
46
46
|
React.useEffect(function () {
|
|
47
|
-
playerRef.current = new _Player.Player(five);
|
|
47
|
+
playerRef.current = new _Player.Player(five, props.configs || {});
|
|
48
48
|
setPlayer(playerRef.current);
|
|
49
49
|
return function () {
|
|
50
50
|
var _playerRef$current;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mode, Pose
|
|
1
|
+
import { Mode, Pose } from '@realsee/five';
|
|
2
2
|
import { CameraMovementEffect, Rotation } from '../fivePlugins/CameraMovementPlugin/typings';
|
|
3
3
|
export declare enum VreoKeyframeEnum {
|
|
4
4
|
/** 运镜 */
|
|
@@ -35,6 +35,10 @@ export declare enum VreoKeyframeEnum {
|
|
|
35
35
|
* 视频特效
|
|
36
36
|
*/
|
|
37
37
|
VideoEffect = "VideoEffect",
|
|
38
|
+
/**
|
|
39
|
+
* 背景音乐
|
|
40
|
+
*/
|
|
41
|
+
BgMusic = "BgMusic",
|
|
38
42
|
/**
|
|
39
43
|
* 结束
|
|
40
44
|
*/
|
|
@@ -57,6 +61,7 @@ export declare type VreoKeyframeConfigMap = {
|
|
|
57
61
|
* 剧本关键帧
|
|
58
62
|
*/
|
|
59
63
|
export interface VreoKeyframe {
|
|
64
|
+
uuid: string;
|
|
60
65
|
type: VreoKeyframeEnum;
|
|
61
66
|
start: number;
|
|
62
67
|
end: number;
|
|
@@ -89,8 +94,10 @@ export interface VreoUnit {
|
|
|
89
94
|
export declare type VreoKeyframeEvent = {
|
|
90
95
|
[key in VreoKeyframeEnum]: (keyframe: VreoKeyframe) => void;
|
|
91
96
|
} & {
|
|
97
|
+
loaded: (vreoUnit: VreoUnit) => void;
|
|
92
98
|
paused: () => void;
|
|
93
99
|
playing: () => void;
|
|
100
|
+
unknownKeyframeType: (keyframe: Record<string, any>) => void;
|
|
94
101
|
};
|
|
95
102
|
/**
|
|
96
103
|
* 相机运动
|
|
@@ -113,9 +120,22 @@ export declare type PrompterData = {
|
|
|
113
120
|
* VR 全景切换
|
|
114
121
|
*/
|
|
115
122
|
export declare type UpdateVRPanoramaData = {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
_signature: string;
|
|
124
|
+
allow_hosts: string[];
|
|
125
|
+
certificate: string;
|
|
126
|
+
expire_at: string;
|
|
127
|
+
dynamic_scene?: {
|
|
128
|
+
images: {
|
|
129
|
+
index: number;
|
|
130
|
+
right: string;
|
|
131
|
+
left: string;
|
|
132
|
+
up: string;
|
|
133
|
+
down: string;
|
|
134
|
+
front: string;
|
|
135
|
+
back: string;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
[key: string]: any;
|
|
119
139
|
};
|
|
120
140
|
/**
|
|
121
141
|
* 顶点
|
|
@@ -196,6 +216,8 @@ export declare enum InfoPanelTypeEnum {
|
|
|
196
216
|
export declare type InfoPanelData = {
|
|
197
217
|
type: InfoPanelTypeEnum;
|
|
198
218
|
url: string;
|
|
219
|
+
title?: string;
|
|
220
|
+
subTitle?: string;
|
|
199
221
|
};
|
|
200
222
|
/**
|
|
201
223
|
* 视频特效
|
|
@@ -207,5 +229,11 @@ export declare type VideoEffectData = {
|
|
|
207
229
|
direction?: Vertex;
|
|
208
230
|
vector?: Pick<Pose, 'longitude' | 'latitude'>;
|
|
209
231
|
};
|
|
232
|
+
/**
|
|
233
|
+
* 背景音乐
|
|
234
|
+
*/
|
|
235
|
+
export declare type BgMusicData = {
|
|
236
|
+
url: string;
|
|
237
|
+
};
|
|
210
238
|
/** 自定义序列帧 */
|
|
211
239
|
export declare type CustomData = Record<string, any>;
|
package/lib/typings/VreoUnit.js
CHANGED
|
@@ -21,6 +21,7 @@ exports.VreoKeyframeEnum = VreoKeyframeEnum;
|
|
|
21
21
|
VreoKeyframeEnum["PanoEffect"] = "PanoEffect";
|
|
22
22
|
VreoKeyframeEnum["InfoPanel"] = "InfoPanel";
|
|
23
23
|
VreoKeyframeEnum["VideoEffect"] = "VideoEffect";
|
|
24
|
+
VreoKeyframeEnum["BgMusic"] = "BgMusic";
|
|
24
25
|
VreoKeyframeEnum["Exit"] = "Exit";
|
|
25
26
|
VreoKeyframeEnum["Custom"] = "Custom";
|
|
26
27
|
})(VreoKeyframeEnum || (exports.VreoKeyframeEnum = VreoKeyframeEnum = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realsee/vreo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-alpha.2",
|
|
4
4
|
"description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realsee",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"packages": "node ./dev-tools/build-packages.js"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@realsee/five": "^5.0.0-alpha.
|
|
28
|
+
"@realsee/five": "^5.0.0-alpha.103",
|
|
29
29
|
"react": "^16.0.0",
|
|
30
30
|
"react-dom": "^16.0.0"
|
|
31
31
|
},
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"@babel/preset-env": "^7.16.4",
|
|
36
36
|
"@babel/preset-react": "^7.16.0",
|
|
37
37
|
"@babel/preset-typescript": "^7.16.0",
|
|
38
|
-
"@realsee/
|
|
38
|
+
"@realsee/dnalogel": "^0.1.7-alpha.10",
|
|
39
|
+
"@realsee/five": "^5.0.0-alpha.103",
|
|
39
40
|
"@types/offscreencanvas": "^2019.6.4",
|
|
40
41
|
"@types/react": "^17.0.37",
|
|
41
42
|
"@types/react-dom": "^17.0.11",
|
package/resources/Player/App.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import * as React from 'react'
|
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
4
|
import { Controller } from './Controller'
|
|
5
|
-
import { useController } from './hooks'
|
|
5
|
+
import { useController, useFiveInstance } from './hooks'
|
|
6
6
|
import { CameraMovement } from './modules/keyframes/CameraMovement'
|
|
7
7
|
import { InfoPanel } from './modules/keyframes/InfoPanel'
|
|
8
8
|
import { ModelVideo } from './modules/keyframes/ModelVideo'
|
|
@@ -13,6 +13,7 @@ import { Prompter } from './modules/keyframes/Prompter'
|
|
|
13
13
|
import { UpdateVRPanorama } from './modules/keyframes/UpdateVRPanorama'
|
|
14
14
|
import { VideoEffect } from './modules/keyframes/VideoEffect'
|
|
15
15
|
import { VideoAgent } from './modules/VideoAgent'
|
|
16
|
+
import { BgMusic } from './modules/keyframes/BgMusic'
|
|
16
17
|
|
|
17
18
|
const AppView = observer(({ controller }: { controller: Controller }) => {
|
|
18
19
|
return (
|
|
@@ -35,6 +36,7 @@ const AppView = observer(({ controller }: { controller: Controller }) => {
|
|
|
35
36
|
}}
|
|
36
37
|
/>
|
|
37
38
|
<Prompter />
|
|
39
|
+
{controller.configs?.customPanelChildren}
|
|
38
40
|
</div>
|
|
39
41
|
</div>
|
|
40
42
|
)
|
|
@@ -53,6 +55,7 @@ export function App() {
|
|
|
53
55
|
<PanoTextLabel />
|
|
54
56
|
<InfoPanel />
|
|
55
57
|
<PanoEffect />
|
|
58
|
+
<BgMusic />
|
|
56
59
|
</>
|
|
57
60
|
<AppView controller={controller} />
|
|
58
61
|
</>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import ReactDOM from 'react-dom'
|
|
3
|
+
import { Five } from '@realsee/five'
|
|
4
|
+
import { Raycaster, Vector3 } from 'three'
|
|
5
|
+
import { tweenProgress } from '@realsee/dnalogel/shared-utils/animationFrame/BetterTween'
|
|
6
|
+
import { CSS3DRenderPlugin, CSS3DRenderPluginExportType } from '@realsee/dnalogel/plugins/CSS3DRenderPlugin'
|
|
7
|
+
|
|
8
|
+
import { VreoKeyframe, VreoKeyframeEnum } from '../../../typings/VreoUnit'
|
|
9
|
+
import { CustomVreoKeyframeProps } from '../../typings'
|
|
10
|
+
|
|
11
|
+
export interface SpatialScenePanelData {
|
|
12
|
+
customType: 'SpatialScenePanel'
|
|
13
|
+
title: string
|
|
14
|
+
temperature: string
|
|
15
|
+
stateList: {
|
|
16
|
+
text: string
|
|
17
|
+
icon: string
|
|
18
|
+
}[]
|
|
19
|
+
position: { x: number; y: number; z: number }
|
|
20
|
+
quaternion: [number, number, number, number]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SearchParams {
|
|
24
|
+
five: Five
|
|
25
|
+
position: Vector3
|
|
26
|
+
rotation?: Vector3
|
|
27
|
+
quaternion: [number, number, number, number]
|
|
28
|
+
dom: HTMLDivElement
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const searchV1 = ({ five, position, rotation, dom }: SearchParams) => {
|
|
32
|
+
const cameraDirection = new Vector3()
|
|
33
|
+
five.camera.getWorldDirection(cameraDirection)
|
|
34
|
+
const cameraPosition = five.camera.position
|
|
35
|
+
const [intersect] = five.model.intersectRaycaster(new Raycaster(cameraPosition, cameraDirection))
|
|
36
|
+
const point = five.project2d(intersect.point)
|
|
37
|
+
|
|
38
|
+
// const width = dom!.clientWidth
|
|
39
|
+
const height = dom!.clientHeight
|
|
40
|
+
dom!.style.left = point!.x + 'px'
|
|
41
|
+
dom!.style.top = point!.y - height / 2 + 'px'
|
|
42
|
+
const rect = dom!.getBoundingClientRect()
|
|
43
|
+
const { left, top, bottom, right } = rect
|
|
44
|
+
|
|
45
|
+
const leftBottom = new Vector3(left, bottom)
|
|
46
|
+
const leftTop = new Vector3(left, top)
|
|
47
|
+
const rightTop = new Vector3(right, top)
|
|
48
|
+
const rightBottom = new Vector3(right, bottom)
|
|
49
|
+
|
|
50
|
+
const points = [leftBottom, rightBottom, rightTop, leftTop].map((point) => {
|
|
51
|
+
point.setX((point.x / window.innerWidth) * 2 - 1)
|
|
52
|
+
point.setY(-(point.y / window.innerHeight) * 2 + 1)
|
|
53
|
+
point.setZ(0.5)
|
|
54
|
+
return point.unproject(five.camera).addScaledVector(cameraDirection, 0.2)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// const colors = [0xdc143c, 0xffff00, 0x0000ff, 0x008000]
|
|
58
|
+
// points.forEach((p, index) => five.scene.add(getSphere(p, colors[index])))
|
|
59
|
+
|
|
60
|
+
const ratio = leftBottom.distanceTo(rightBottom) / 160
|
|
61
|
+
return { points, ratio }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 空间场景面板
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
export function SpatialScenePanel(props: CustomVreoKeyframeProps) {
|
|
69
|
+
const ref = React.useRef<HTMLDivElement>(null)
|
|
70
|
+
const panelRef = React.useRef<HTMLDivElement | null>(null)
|
|
71
|
+
const rendererRef = React.useRef<CSS3DRenderPluginExportType>(CSS3DRenderPlugin(props.five))
|
|
72
|
+
|
|
73
|
+
React.useEffect(() => {
|
|
74
|
+
|
|
75
|
+
if (!ref.current) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const callback = (keyframe: VreoKeyframe) => {
|
|
80
|
+
if (keyframe.data.customType !== 'SpatialScenePanel') {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const data = keyframe.data as SpatialScenePanelData
|
|
85
|
+
// const data = mockData as SpatialScenePanelData
|
|
86
|
+
|
|
87
|
+
const { points, ratio } = searchV1({
|
|
88
|
+
five: props.five,
|
|
89
|
+
position: new Vector3(data.position.x, data.position.y, data.position.z),
|
|
90
|
+
quaternion: data.quaternion,
|
|
91
|
+
dom: ref.current!
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
console.log(points, ratio)
|
|
95
|
+
|
|
96
|
+
const { container, dispose, css3DObject, render } =
|
|
97
|
+
rendererRef.current.create3DDomContainer(points, { ratio, autoRender: false }) || {}
|
|
98
|
+
|
|
99
|
+
if (!container) return
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
ReactDOM.render(<Panel ref={(ref) => (panelRef.current = ref)} data={data} />, container)
|
|
103
|
+
const startRotateY = -(Math.PI * 2) / 9
|
|
104
|
+
let lastRotateY = 0
|
|
105
|
+
tweenProgress(1000)
|
|
106
|
+
.onUpdate(({ progress }) => {
|
|
107
|
+
const needRotateY = (Math.PI / 90) * 11 * progress
|
|
108
|
+
const rotateY = needRotateY - lastRotateY
|
|
109
|
+
css3DObject?.rotateY(rotateY)
|
|
110
|
+
lastRotateY = needRotateY
|
|
111
|
+
})
|
|
112
|
+
.onStart(() => {
|
|
113
|
+
css3DObject?.rotateY(startRotateY)
|
|
114
|
+
render!()
|
|
115
|
+
})
|
|
116
|
+
.onDispose(() => {
|
|
117
|
+
panelRef.current?.classList.add('show')
|
|
118
|
+
})
|
|
119
|
+
.play()
|
|
120
|
+
const { start, end } = keyframe
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
panelRef.current?.classList.add('hide')
|
|
123
|
+
setTimeout(() => dispose?.(), 1500)
|
|
124
|
+
}, end - start)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Object.assign(window, {$SpatialScenePanelCallback: callback})
|
|
128
|
+
props.subscribe.on(VreoKeyframeEnum.Custom, callback)
|
|
129
|
+
|
|
130
|
+
return () => {
|
|
131
|
+
props.subscribe.off(VreoKeyframeEnum.Custom, callback)
|
|
132
|
+
}
|
|
133
|
+
}, [])
|
|
134
|
+
|
|
135
|
+
return <div className="vreo-SpatialScenePanel" ref={ref}></div>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const Panel = React.forwardRef(
|
|
139
|
+
(props: { data: SpatialScenePanelData }, myRef: React.LegacyRef<HTMLDivElement> | undefined) => (
|
|
140
|
+
<div className="SpatialScenePanel" ref={myRef}>
|
|
141
|
+
<div className="SpatialScenePanel-show-area">
|
|
142
|
+
<div className="SpatialScenePanel-bg"></div>
|
|
143
|
+
<div className="SpatialScenePanel-header">
|
|
144
|
+
<div className="SpatialScenePanel-title">{props.data?.title}</div>
|
|
145
|
+
<div className="SpatialScenePanel-temperature">{props.data?.temperature}℃</div>
|
|
146
|
+
</div>
|
|
147
|
+
<div className="SpatialScenePanel-body">
|
|
148
|
+
{props.data?.stateList?.map((state, index) => (
|
|
149
|
+
<div key={`scene-${state.text}`} className={`SpatialScenePanel-item index_${index}`}>
|
|
150
|
+
<img className="SpatialScenePanel-icon" src={state.icon}></img>
|
|
151
|
+
<div className="SpatialScenePanel-text">{state.text}</div>
|
|
152
|
+
<div className="SpatialScenePanel-dot"></div>
|
|
153
|
+
</div>
|
|
154
|
+
))}
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div className="SpatialScenePanel-disappear-area"></div>
|
|
159
|
+
</div>
|
|
160
|
+
),
|
|
161
|
+
)
|
|
@@ -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,
|
|
7
|
+
import { VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
|
|
8
8
|
import { reaction } from 'mobx'
|
|
9
9
|
import { Drawer } from './modules/Drawer'
|
|
10
10
|
import { PlayerConfigs } from './typings'
|
|
@@ -42,6 +42,18 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
42
42
|
<ControllerContext.Provider value={this.controller}>
|
|
43
43
|
<App></App>
|
|
44
44
|
<Drawer />
|
|
45
|
+
{this.configs.customKeyframes &&
|
|
46
|
+
this.configs.customKeyframes.map((CustomCmpt, key) => (
|
|
47
|
+
<CustomCmpt
|
|
48
|
+
key={key}
|
|
49
|
+
subscribe={{
|
|
50
|
+
on: (name, callback) => this.on(name, callback),
|
|
51
|
+
once: (name, callback) => this.once(name, callback),
|
|
52
|
+
off: (name, callback) => this.off(name, callback),
|
|
53
|
+
}}
|
|
54
|
+
five={five}
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
45
57
|
</ControllerContext.Provider>,
|
|
46
58
|
configs.containter
|
|
47
59
|
)
|
|
@@ -58,6 +70,7 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
58
70
|
async load(vreoUnit: VreoUnit, currentTime = 0) {
|
|
59
71
|
if (!this.controller.visible) {
|
|
60
72
|
this.controller.setVisible(true)
|
|
73
|
+
// 延迟 500ms 规避跟 DOM 动画冲突
|
|
61
74
|
await new Promise((resolve) => {
|
|
62
75
|
setTimeout(() => resolve(true), 500)
|
|
63
76
|
})
|
|
@@ -71,6 +84,8 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
71
84
|
this.controller.vreoUnit = vreoUnit
|
|
72
85
|
this.controller.videoInstance?.pause()
|
|
73
86
|
|
|
87
|
+
// 新数据载入就绪
|
|
88
|
+
this.emit('loaded', vreoUnit)
|
|
74
89
|
if (vreoUnit.video.url) {
|
|
75
90
|
if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
|
|
76
91
|
this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
@@ -5,7 +5,7 @@ import { Controller } from '../../Controller'
|
|
|
5
5
|
import { useController } from '../../hooks'
|
|
6
6
|
|
|
7
7
|
const DrawerView = observer(({ controller }: { controller: Controller }) => {
|
|
8
|
-
const maxHeight = '
|
|
8
|
+
const maxHeight = '400px'
|
|
9
9
|
const height = (() => {
|
|
10
10
|
const height = controller.drawerConfig?.height
|
|
11
11
|
if (!height) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { BgMusicData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
3
|
+
import { useController } from '../../../hooks'
|
|
4
|
+
|
|
5
|
+
export function BgMusic() {
|
|
6
|
+
const controller = useController()
|
|
7
|
+
const timeoutIdRef = React.useRef<NodeJS.Timeout | null>(null)
|
|
8
|
+
const cleanTimeout = React.useCallback( () => {
|
|
9
|
+
if (timeoutIdRef.current) {
|
|
10
|
+
clearTimeout(timeoutIdRef.current)
|
|
11
|
+
timeoutIdRef.current = null
|
|
12
|
+
}
|
|
13
|
+
}, [])
|
|
14
|
+
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
const audio = new Audio()
|
|
17
|
+
audio.setAttribute('id', 'vreo-singleton-bgmusic')
|
|
18
|
+
audio.style.display = 'none'
|
|
19
|
+
|
|
20
|
+
audio.setAttribute('playsinline', 'true')
|
|
21
|
+
audio.loop = true
|
|
22
|
+
document.body.append(audio)
|
|
23
|
+
|
|
24
|
+
const callback = (keyframe: VreoKeyframe) => {
|
|
25
|
+
const { start, end } = keyframe
|
|
26
|
+
const { url } = keyframe.data as BgMusicData
|
|
27
|
+
audio.src = url
|
|
28
|
+
const playCallback = () => {
|
|
29
|
+
audio.play()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
audio.addEventListener('canplaythrough', playCallback)
|
|
33
|
+
|
|
34
|
+
cleanTimeout()
|
|
35
|
+
|
|
36
|
+
const cleanAudio = () => {
|
|
37
|
+
audio.pause()
|
|
38
|
+
audio.currentTime = 0
|
|
39
|
+
audio.src = ''
|
|
40
|
+
cleanTimeout()
|
|
41
|
+
audio.removeEventListener('canplaythrough', playCallback)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const duration = (end - start) || 5000
|
|
45
|
+
|
|
46
|
+
timeoutIdRef.current = setTimeout(() => {
|
|
47
|
+
cleanAudio()
|
|
48
|
+
}, duration)
|
|
49
|
+
|
|
50
|
+
controller.once('paused', () => {
|
|
51
|
+
cleanAudio()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
controller.on(VreoKeyframeEnum.BgMusic, callback)
|
|
57
|
+
|
|
58
|
+
return () => {
|
|
59
|
+
controller.off(VreoKeyframeEnum.BgMusic, callback)
|
|
60
|
+
document.body.removeChild(audio)
|
|
61
|
+
cleanTimeout()
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
return <></>
|
|
66
|
+
}
|