@realsee/vreo 0.1.1 → 0.1.5
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/docs/assets/search.js +1 -1
- package/docs/classes/Player.Player-1.html +6 -6
- 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 +13 -11
- package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
- package/docs/enums/fivePlugins.Rotation.html +1 -1
- package/docs/interfaces/Player.PlayerConfigs.html +1 -1
- package/docs/interfaces/Player.Vertex.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/modules/Player.html +14 -12
- package/docs/modules/fivePlugins.html +2 -2
- package/docs/modules/react.html +1 -1
- package/lib/Player/App.js +4 -0
- package/lib/Player/Controller.d.ts +1 -0
- package/lib/Player/Controller.js +11 -4
- package/lib/Player/index.d.ts +1 -0
- package/lib/Player/index.js +50 -31
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +2 -0
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +62 -22
- package/lib/Player/modules/VideoAgent/VideoAgentScene.d.ts +2 -0
- package/lib/Player/modules/VideoAgent/VideoAgentScene.js +7 -0
- package/lib/Player/modules/VideoAgent/index.js +6 -0
- package/lib/Player/modules/keyframes/Prompter/index.js +2 -1
- package/lib/react/index.js +27 -7
- package/lib/typings/VreoUnit.d.ts +7 -1
- package/lib/typings/VreoUnit.js +1 -0
- package/package.json +6 -2
- package/resources/Player/App.tsx +3 -0
- package/resources/Player/Controller.ts +5 -5
- package/resources/Player/index.tsx +36 -23
- package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +63 -20
- package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +6 -0
- package/resources/Player/modules/VideoAgent/index.tsx +5 -0
- package/resources/Player/modules/keyframes/Prompter/index.tsx +1 -0
- package/resources/react/index.tsx +20 -3
- package/resources/typings/VreoUnit.ts +7 -0
- package/stylesheets/default.css +9 -1
|
@@ -47,6 +47,8 @@ var fragmentShaderTpl = function fragmentShaderTpl() {
|
|
|
47
47
|
return "\nuniform int enable;\nuniform sampler2D map;\nvarying vec2 vUv;\nvarying vec2 vColorUv;\nvarying vec2 vMaskUv;\n\nvec3 hsv2rgb(vec3 c) {\n const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvec3 rgb2hsv(vec3 c) {\n const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + 0.001)), d / (q.x + 0.001), q.x);\n}\n\nvoid main(void) {\n vec3 color = texture2D(map, vUv).xyz;\n float amask = 1.0;\n\n float ref = color.r;\n if (ref < color.b) ref = color.b;\n amask = color.g - ref + 0.1;\n amask = smoothstep(0.1, 0.3, amask);\n amask = 1.0 - amask;\n\n vec3 target = rgb2hsv(vec3(0.0 / 255.0, 255.0 / 255.0, 0.0 / 255.0));\n vec3 hsv = rgb2hsv(color);\n float distance = abs(hsv.x - target.x);\n if (distance < 0.15) {\n hsv.y = 0.0;\n }\n color = hsv2rgb(hsv);\n\n gl_FragColor = vec4(color.rgb, amask * float(enable));\n}\n";
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
+
var cacheInstance = {};
|
|
51
|
+
|
|
50
52
|
/**
|
|
51
53
|
* 视频经纪人MESH
|
|
52
54
|
*/
|
|
@@ -71,13 +73,18 @@ var VideoAgentMesh = /*#__PURE__*/function (_THREE$Mesh) {
|
|
|
71
73
|
_classCallCheck(this, VideoAgentMesh);
|
|
72
74
|
|
|
73
75
|
if (!options.videoInstance) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
if (cacheInstance.videoInstance) {
|
|
77
|
+
options.videoInstance = cacheInstance.videoInstance;
|
|
78
|
+
} else {
|
|
79
|
+
var videoInstance = document.createElement('video');
|
|
80
|
+
videoInstance.style.opacity = '0';
|
|
81
|
+
videoInstance.style.display = 'none';
|
|
82
|
+
document.body.append(videoInstance);
|
|
83
|
+
options.videoInstance = videoInstance;
|
|
84
|
+
cacheInstance.videoInstance = videoInstance;
|
|
85
|
+
videoInstance.playsInline = true;
|
|
86
|
+
videoInstance.controls = false;
|
|
87
|
+
}
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
var geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
|
|
@@ -100,16 +107,21 @@ var VideoAgentMesh = /*#__PURE__*/function (_THREE$Mesh) {
|
|
|
100
107
|
_this.freeze = false;
|
|
101
108
|
_this.paused = true;
|
|
102
109
|
{
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
if (cacheInstance.audioInstance) {
|
|
111
|
+
_this.audioInstance = cacheInstance.audioInstance;
|
|
112
|
+
} else {
|
|
113
|
+
var audioInstance = document.createElement('audio');
|
|
114
|
+
audioInstance.crossOrigin = ''; // videoInstance.muted = true
|
|
115
|
+
|
|
116
|
+
audioInstance.muted = false;
|
|
117
|
+
audioInstance.setAttribute('playsinline', 'true');
|
|
118
|
+
audioInstance.setAttribute('webkit-playsinline', 'true');
|
|
119
|
+
audioInstance.setAttribute('autoplay', 'false');
|
|
120
|
+
audioInstance.setAttribute('style', 'display: none;');
|
|
121
|
+
document.body.appendChild(audioInstance);
|
|
122
|
+
_this.audioInstance = audioInstance;
|
|
123
|
+
cacheInstance.audioInstance = audioInstance;
|
|
124
|
+
}
|
|
113
125
|
}
|
|
114
126
|
(0, _mobx.makeObservable)(_assertThisInitialized(_this), {
|
|
115
127
|
paused: _mobx.observable
|
|
@@ -121,13 +133,23 @@ var VideoAgentMesh = /*#__PURE__*/function (_THREE$Mesh) {
|
|
|
121
133
|
});
|
|
122
134
|
};
|
|
123
135
|
|
|
124
|
-
|
|
136
|
+
var onPause = function onPause() {
|
|
125
137
|
return updatePaused(true);
|
|
126
|
-
}
|
|
138
|
+
};
|
|
127
139
|
|
|
128
|
-
|
|
140
|
+
var onPlay = function onPlay() {
|
|
129
141
|
return updatePaused(false);
|
|
130
|
-
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
_this.videoInstance.addEventListener('pause', onPause);
|
|
145
|
+
|
|
146
|
+
_this.videoInstance.addEventListener('play', onPlay);
|
|
147
|
+
|
|
148
|
+
_this.$removeEventListener = function () {
|
|
149
|
+
_this.videoInstance.removeEventListener('pause', onPause);
|
|
150
|
+
|
|
151
|
+
_this.videoInstance.removeEventListener('play', onPlay);
|
|
152
|
+
};
|
|
131
153
|
|
|
132
154
|
return _this;
|
|
133
155
|
}
|
|
@@ -186,10 +208,12 @@ var VideoAgentMesh = /*#__PURE__*/function (_THREE$Mesh) {
|
|
|
186
208
|
this.videoInstance.setAttribute('data-src', this.videoUrl);
|
|
187
209
|
|
|
188
210
|
onStart = function onStart() {
|
|
211
|
+
var _this2$videoUrl;
|
|
212
|
+
|
|
189
213
|
if (_this2.videoInstance.currentTime === 0) return;
|
|
190
214
|
_this2.freeze = false;
|
|
191
215
|
_this2.videoInstance.muted = false;
|
|
192
|
-
uniforms.enable.value = 1;
|
|
216
|
+
uniforms.enable.value = (_this2$videoUrl = _this2.videoUrl) !== null && _this2$videoUrl !== void 0 && _this2$videoUrl.endsWith('.mp4') ? 1 : 0;
|
|
193
217
|
|
|
194
218
|
_this2.videoInstance.removeEventListener('timeupdate', onStart, false);
|
|
195
219
|
};
|
|
@@ -316,6 +340,22 @@ var VideoAgentMesh = /*#__PURE__*/function (_THREE$Mesh) {
|
|
|
316
340
|
get: function get() {
|
|
317
341
|
return this.videoInstance.currentTime * 1000;
|
|
318
342
|
}
|
|
343
|
+
}, {
|
|
344
|
+
key: "dispose",
|
|
345
|
+
value: function dispose() {
|
|
346
|
+
// 销毁事件监听
|
|
347
|
+
this.$removeEventListener();
|
|
348
|
+
|
|
349
|
+
if (cacheInstance.audioInstance) {
|
|
350
|
+
document.body.removeChild(cacheInstance.audioInstance);
|
|
351
|
+
cacheInstance.audioInstance = undefined;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (cacheInstance.videoInstance) {
|
|
355
|
+
document.body.removeChild(cacheInstance.videoInstance);
|
|
356
|
+
cacheInstance.videoInstance = undefined;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
319
359
|
}]);
|
|
320
360
|
|
|
321
361
|
return VideoAgentMesh;
|
|
@@ -43,6 +43,13 @@ var VideoAgentScene = function VideoAgentScene(container) {
|
|
|
43
43
|
requestAnimationFrame(_this.run);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
_defineProperty(this, "dispose", function () {
|
|
47
|
+
var _this$videoAgentMesh;
|
|
48
|
+
|
|
49
|
+
(_this$videoAgentMesh = _this.videoAgentMesh) === null || _this$videoAgentMesh === void 0 ? void 0 : _this$videoAgentMesh.dispose();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.container = container;
|
|
46
53
|
this.camera.position.set(0, 0, 10);
|
|
47
54
|
this.camera.lookAt(0, 0, 0);
|
|
48
55
|
var state = {
|
|
@@ -30,6 +30,12 @@ function VideoAgent(props) {
|
|
|
30
30
|
|
|
31
31
|
var videoAgentScene = new _VideoAgentScene.VideoAgentScene(ref.current);
|
|
32
32
|
controller.videoAgentScene = videoAgentScene;
|
|
33
|
+
return function () {
|
|
34
|
+
var _controller$videoAgen;
|
|
35
|
+
|
|
36
|
+
controller.dispose();
|
|
37
|
+
(_controller$videoAgen = controller.videoAgentScene) === null || _controller$videoAgen === void 0 ? void 0 : _controller$videoAgen.dispose();
|
|
38
|
+
};
|
|
33
39
|
}, []);
|
|
34
40
|
return /*#__PURE__*/React.createElement("div", {
|
|
35
41
|
className: "VideoAgent",
|
|
@@ -84,7 +84,8 @@ function Prompter() {
|
|
|
84
84
|
}, [controller]);
|
|
85
85
|
return /*#__PURE__*/React.createElement("div", {
|
|
86
86
|
className: (0, _classnames["default"])('vreo-prompter', {
|
|
87
|
-
'vreo-prompter--hidden': hidden
|
|
87
|
+
'vreo-prompter--hidden': hidden,
|
|
88
|
+
'vreo-prompter--audio': controller.isAudio
|
|
88
89
|
})
|
|
89
90
|
}, text ?
|
|
90
91
|
/*#__PURE__*/
|
package/lib/react/index.js
CHANGED
|
@@ -36,7 +36,23 @@ var VreoContext = /*#__PURE__*/React.createContext(null);
|
|
|
36
36
|
|
|
37
37
|
var VreoProvider = function VreoProvider(props) {
|
|
38
38
|
var five = (0, _react.unsafe__useFiveInstance)();
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
var _React$useState = React.useState(null),
|
|
41
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
42
|
+
player = _React$useState2[0],
|
|
43
|
+
setPlayer = _React$useState2[1];
|
|
44
|
+
|
|
45
|
+
var playerRef = React.useRef(null);
|
|
46
|
+
React.useEffect(function () {
|
|
47
|
+
playerRef.current = new _Player.Player(five);
|
|
48
|
+
setPlayer(playerRef.current);
|
|
49
|
+
return function () {
|
|
50
|
+
var _playerRef$current;
|
|
51
|
+
|
|
52
|
+
(_playerRef$current = playerRef.current) === null || _playerRef$current === void 0 ? void 0 : _playerRef$current.dispose();
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
if (!player) return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
40
56
|
return /*#__PURE__*/React.createElement(VreoContext.Provider, {
|
|
41
57
|
value: player
|
|
42
58
|
}, props.children);
|
|
@@ -96,19 +112,23 @@ function useVreoEventCallback(name, callback, deps) {
|
|
|
96
112
|
dependencyList = dependencyList.concat(deps);
|
|
97
113
|
}
|
|
98
114
|
|
|
99
|
-
React.
|
|
115
|
+
React.useEffect(function () {
|
|
100
116
|
// @ts-ignore
|
|
101
|
-
|
|
117
|
+
player.on(name, callback);
|
|
118
|
+
return function () {
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
player.off(name, callback);
|
|
121
|
+
};
|
|
102
122
|
}, dependencyList);
|
|
103
123
|
}
|
|
104
124
|
|
|
105
125
|
function useVreoPausedState() {
|
|
106
126
|
var player = useVreoInstance();
|
|
107
127
|
|
|
108
|
-
var _React$
|
|
109
|
-
_React$
|
|
110
|
-
state = _React$
|
|
111
|
-
setState = _React$
|
|
128
|
+
var _React$useState3 = React.useState(player.paused),
|
|
129
|
+
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
130
|
+
state = _React$useState4[0],
|
|
131
|
+
setState = _React$useState4[1];
|
|
112
132
|
|
|
113
133
|
useVreoEventCallback('paused', function () {
|
|
114
134
|
return setState(true);
|
|
@@ -38,7 +38,11 @@ export declare enum VreoKeyframeEnum {
|
|
|
38
38
|
/**
|
|
39
39
|
* 结束
|
|
40
40
|
*/
|
|
41
|
-
Exit = "Exit"
|
|
41
|
+
Exit = "Exit",
|
|
42
|
+
/**
|
|
43
|
+
* 自定义剧本帧
|
|
44
|
+
*/
|
|
45
|
+
Custom = "Custom"
|
|
42
46
|
}
|
|
43
47
|
/**
|
|
44
48
|
* 支持自定义剧本关键帧配置项
|
|
@@ -202,3 +206,5 @@ export declare type VideoEffectData = {
|
|
|
202
206
|
direction?: Vertex;
|
|
203
207
|
vector?: Pick<Pose, 'longitude' | 'latitude'>;
|
|
204
208
|
};
|
|
209
|
+
/** 自定义序列帧 */
|
|
210
|
+
export declare type CustomData = Record<string, any>;
|
package/lib/typings/VreoUnit.js
CHANGED
|
@@ -22,6 +22,7 @@ exports.VreoKeyframeEnum = VreoKeyframeEnum;
|
|
|
22
22
|
VreoKeyframeEnum["InfoPanel"] = "InfoPanel";
|
|
23
23
|
VreoKeyframeEnum["VideoEffect"] = "VideoEffect";
|
|
24
24
|
VreoKeyframeEnum["Exit"] = "Exit";
|
|
25
|
+
VreoKeyframeEnum["Custom"] = "Custom";
|
|
25
26
|
})(VreoKeyframeEnum || (exports.VreoKeyframeEnum = VreoKeyframeEnum = {}));
|
|
26
27
|
|
|
27
28
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realsee/vreo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"realsee",
|
|
7
|
+
"vreo"
|
|
8
|
+
],
|
|
5
9
|
"main": "lib/index.js",
|
|
6
10
|
"author": "BEIKE REALSEE TECHNOLOGY (HK) LIMITED",
|
|
7
11
|
"license": "MIT",
|
|
@@ -31,7 +35,7 @@
|
|
|
31
35
|
"@babel/preset-env": "^7.16.4",
|
|
32
36
|
"@babel/preset-react": "^7.16.0",
|
|
33
37
|
"@babel/preset-typescript": "^7.16.0",
|
|
34
|
-
"@realsee/five": "^5.0.0-alpha.
|
|
38
|
+
"@realsee/five": "^5.0.0-alpha.80",
|
|
35
39
|
"@types/offscreencanvas": "^2019.6.4",
|
|
36
40
|
"@types/react": "^17.0.37",
|
|
37
41
|
"@types/react-dom": "^17.0.11",
|
package/resources/Player/App.tsx
CHANGED
|
@@ -24,6 +24,9 @@ const AppView = observer(({ controller }: { controller: Controller }) => {
|
|
|
24
24
|
<div className="vreo-panel-inner">
|
|
25
25
|
<VideoAgent
|
|
26
26
|
onClick={() => {
|
|
27
|
+
if (controller.isAudio) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
27
30
|
if (controller.playing) {
|
|
28
31
|
controller.setPlaying(false)
|
|
29
32
|
} else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Five, Subscribe } from '@realsee/five'
|
|
2
|
-
import { action, makeObservable, observable, reaction } from 'mobx'
|
|
2
|
+
import { action, computed, makeObservable, observable, reaction } from 'mobx'
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { requestAnimationFrameInterval } from '../shared-utils/animationFrame'
|
|
5
5
|
import { VreoKeyframe, VreoKeyframeEnum, VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
|
|
@@ -20,6 +20,10 @@ export class Controller extends Subscribe<VreoKeyframeEvent> {
|
|
|
20
20
|
|
|
21
21
|
visible = false
|
|
22
22
|
|
|
23
|
+
get isAudio() {
|
|
24
|
+
return !this.videoAgentScene?.videoAgentMesh.videoUrl?.endsWith('.mp4')
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
drawerConfig: {
|
|
24
28
|
content: string | JSX.Element
|
|
25
29
|
height?: number | string
|
|
@@ -55,7 +59,6 @@ export class Controller extends Subscribe<VreoKeyframeEvent> {
|
|
|
55
59
|
setPlaying: action,
|
|
56
60
|
drawerConfig: observable.ref,
|
|
57
61
|
openDrawer: action,
|
|
58
|
-
|
|
59
62
|
})
|
|
60
63
|
|
|
61
64
|
// 监听播放情况:抛出触发时机
|
|
@@ -149,6 +152,3 @@ export class Controller extends Subscribe<VreoKeyframeEvent> {
|
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
export const ControllerContext = React.createContext<Controller | null>(null)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
@@ -9,18 +9,19 @@ import { reaction } from 'mobx'
|
|
|
9
9
|
import { Drawer } from './modules/Drawer'
|
|
10
10
|
import { PlayerConfigs } from './typings'
|
|
11
11
|
|
|
12
|
-
const controller = new Controller()
|
|
13
|
-
|
|
14
12
|
export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
15
13
|
$five: Five
|
|
14
|
+
private controller: Controller
|
|
16
15
|
configs: Readonly<PlayerConfigs>
|
|
17
16
|
|
|
18
17
|
constructor(five: Five, configs: Partial<PlayerConfigs> = {}) {
|
|
19
18
|
super()
|
|
20
|
-
this
|
|
19
|
+
this.controller = new Controller()
|
|
20
|
+
this.$five = this.controller.$five = five
|
|
21
21
|
|
|
22
22
|
if (!configs.containter) {
|
|
23
|
-
const containter = document.createElement('div')
|
|
23
|
+
const containter = document.querySelector('#vreo-app') || document.createElement('div')
|
|
24
|
+
ReactDOM.unmountComponentAtNode(containter)
|
|
24
25
|
containter.setAttribute('id', 'vreo-app')
|
|
25
26
|
configs.containter = containter
|
|
26
27
|
document.body.append(containter)
|
|
@@ -35,10 +36,10 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
35
36
|
)
|
|
36
37
|
)
|
|
37
38
|
|
|
38
|
-
controller.configs = this.configs
|
|
39
|
+
this.controller.configs = this.configs
|
|
39
40
|
|
|
40
41
|
ReactDOM.render(
|
|
41
|
-
<ControllerContext.Provider value={controller}>
|
|
42
|
+
<ControllerContext.Provider value={this.controller}>
|
|
42
43
|
<App></App>
|
|
43
44
|
<Drawer />
|
|
44
45
|
</ControllerContext.Provider>,
|
|
@@ -47,7 +48,7 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
47
48
|
|
|
48
49
|
// 监听播放情况:抛出触发时机
|
|
49
50
|
reaction(
|
|
50
|
-
() => controller.playing,
|
|
51
|
+
() => this.controller.playing,
|
|
51
52
|
(playing) => {
|
|
52
53
|
this.emit(playing ? 'playing' : 'paused')
|
|
53
54
|
}
|
|
@@ -55,49 +56,61 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
async load(vreoUnit: VreoUnit, currentTime = 0) {
|
|
58
|
-
if (controller.
|
|
59
|
-
controller.
|
|
60
|
-
|
|
59
|
+
if (!this.controller.visible) {
|
|
60
|
+
this.controller.setVisible(true)
|
|
61
|
+
await new Promise((resolve) => {
|
|
62
|
+
setTimeout(() => resolve(true), 500)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (this.controller.stopInterval) {
|
|
67
|
+
this.controller.stopInterval()
|
|
68
|
+
this.controller.stopInterval = undefined
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
controller.vreoUnit = vreoUnit
|
|
64
|
-
controller.videoInstance?.pause()
|
|
71
|
+
this.controller.vreoUnit = vreoUnit
|
|
72
|
+
this.controller.videoInstance?.pause()
|
|
65
73
|
|
|
66
74
|
if (vreoUnit.video.url) {
|
|
67
|
-
if (controller.videoAgentScene?.videoAgentMesh.videoInstance) {
|
|
68
|
-
controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
75
|
+
if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
|
|
76
|
+
this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
69
77
|
}
|
|
70
|
-
await controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
|
|
78
|
+
await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
|
|
71
79
|
this.play()
|
|
72
80
|
}
|
|
73
|
-
controller.run((type, keyframe) => this.emit(type, keyframe))
|
|
81
|
+
this.controller.run((type, keyframe) => this.emit(type, keyframe))
|
|
74
82
|
return true
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
get paused() {
|
|
78
|
-
return !controller.playing
|
|
86
|
+
return !this.controller.playing
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
play() {
|
|
82
|
-
if (controller.playing) return true
|
|
83
|
-
controller.setPlaying(true)
|
|
90
|
+
if (this.controller.playing) return true
|
|
91
|
+
this.controller.setPlaying(true)
|
|
84
92
|
return true
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
pause() {
|
|
88
|
-
controller.setPlaying(false)
|
|
96
|
+
this.controller.setPlaying(false)
|
|
89
97
|
}
|
|
90
98
|
|
|
91
99
|
show() {
|
|
92
|
-
controller.setVisible(true)
|
|
100
|
+
this.controller.setVisible(true)
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
hide() {
|
|
96
|
-
controller.setVisible(false)
|
|
104
|
+
this.controller.setVisible(false)
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
dispose() {
|
|
100
|
-
|
|
108
|
+
this.pause()
|
|
109
|
+
this.controller.dispose()
|
|
110
|
+
|
|
111
|
+
if (this.configs.containter) {
|
|
112
|
+
ReactDOM.unmountComponentAtNode(this.configs.containter as Element)
|
|
113
|
+
}
|
|
101
114
|
}
|
|
102
115
|
}
|
|
103
116
|
|
|
@@ -57,6 +57,11 @@ void main(void) {
|
|
|
57
57
|
}
|
|
58
58
|
`
|
|
59
59
|
|
|
60
|
+
const cacheInstance: {
|
|
61
|
+
videoInstance?: HTMLVideoElement
|
|
62
|
+
audioInstance?: HTMLAudioElement
|
|
63
|
+
} = {}
|
|
64
|
+
|
|
60
65
|
export interface VideoAgentMeshOptions {
|
|
61
66
|
videoInstance?: HTMLVideoElement
|
|
62
67
|
}
|
|
@@ -70,6 +75,7 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
70
75
|
freeze: boolean
|
|
71
76
|
paused: boolean
|
|
72
77
|
audioInstance: HTMLAudioElement
|
|
78
|
+
$removeEventListener: () => void
|
|
73
79
|
|
|
74
80
|
get videoInstance(): HTMLAudioElement {
|
|
75
81
|
if (this.videoUrl?.endsWith('mp3')) {
|
|
@@ -96,13 +102,19 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
96
102
|
options: VideoAgentMeshOptions = {},
|
|
97
103
|
) {
|
|
98
104
|
if (!options.videoInstance) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
if (cacheInstance.videoInstance) {
|
|
106
|
+
options.videoInstance = cacheInstance.videoInstance
|
|
107
|
+
} else {
|
|
108
|
+
const videoInstance = document.createElement('video')
|
|
109
|
+
videoInstance.style.opacity = '0'
|
|
110
|
+
videoInstance.style.display = 'none'
|
|
111
|
+
document.body.append(videoInstance)
|
|
112
|
+
options.videoInstance = videoInstance
|
|
113
|
+
cacheInstance.videoInstance = videoInstance
|
|
114
|
+
videoInstance.playsInline = true
|
|
115
|
+
videoInstance.controls = false
|
|
116
|
+
}
|
|
117
|
+
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
|
|
@@ -123,24 +135,41 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
123
135
|
this.paused = true
|
|
124
136
|
|
|
125
137
|
{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
138
|
+
if (cacheInstance.audioInstance) {
|
|
139
|
+
this.audioInstance = cacheInstance.audioInstance
|
|
140
|
+
|
|
141
|
+
} else {
|
|
142
|
+
const audioInstance = document.createElement('audio')
|
|
143
|
+
audioInstance.crossOrigin = ''
|
|
144
|
+
// videoInstance.muted = true
|
|
145
|
+
audioInstance.muted = false
|
|
146
|
+
audioInstance.setAttribute('playsinline', 'true')
|
|
147
|
+
audioInstance.setAttribute('webkit-playsinline', 'true')
|
|
148
|
+
audioInstance.setAttribute('autoplay', 'false')
|
|
149
|
+
audioInstance.setAttribute('style', 'display: none;')
|
|
150
|
+
document.body.appendChild(audioInstance)
|
|
151
|
+
this.audioInstance = audioInstance
|
|
152
|
+
cacheInstance.audioInstance = audioInstance
|
|
153
|
+
}
|
|
154
|
+
|
|
136
155
|
}
|
|
156
|
+
|
|
137
157
|
makeObservable(this, { paused: observable })
|
|
138
158
|
|
|
139
159
|
const updatePaused = (paused: boolean) => runInAction(() => (this.paused = paused))
|
|
140
|
-
|
|
141
|
-
|
|
160
|
+
const onPause = () => updatePaused(true)
|
|
161
|
+
const onPlay = () => updatePaused(false)
|
|
162
|
+
|
|
163
|
+
this.videoInstance.addEventListener('pause', onPause)
|
|
164
|
+
this.videoInstance.addEventListener('play', onPlay)
|
|
165
|
+
|
|
166
|
+
this.$removeEventListener = () => {
|
|
167
|
+
this.videoInstance.removeEventListener('pause', onPause)
|
|
168
|
+
this.videoInstance.removeEventListener('play', onPlay)
|
|
169
|
+
}
|
|
142
170
|
}
|
|
143
171
|
|
|
172
|
+
|
|
144
173
|
private async update(videoUrl: string) {
|
|
145
174
|
if (this.videoUrl === videoUrl) {
|
|
146
175
|
return
|
|
@@ -159,7 +188,7 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
159
188
|
if (this.videoInstance.currentTime === 0) return
|
|
160
189
|
this.freeze = false
|
|
161
190
|
this.videoInstance.muted = false
|
|
162
|
-
uniforms.enable.value = 1
|
|
191
|
+
uniforms.enable.value = this.videoUrl?.endsWith('.mp4') ? 1 : 0
|
|
163
192
|
this.videoInstance.removeEventListener('timeupdate', onStart, false)
|
|
164
193
|
}
|
|
165
194
|
|
|
@@ -199,4 +228,18 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
199
228
|
get currentTime() {
|
|
200
229
|
return this.videoInstance.currentTime * 1000
|
|
201
230
|
}
|
|
231
|
+
|
|
232
|
+
dispose() {
|
|
233
|
+
// 销毁事件监听
|
|
234
|
+
this.$removeEventListener()
|
|
235
|
+
if (cacheInstance.audioInstance) {
|
|
236
|
+
document.body.removeChild(cacheInstance.audioInstance)
|
|
237
|
+
cacheInstance.audioInstance = undefined
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (cacheInstance.videoInstance) {
|
|
241
|
+
document.body.removeChild(cacheInstance.videoInstance)
|
|
242
|
+
cacheInstance.videoInstance = undefined
|
|
243
|
+
}
|
|
244
|
+
}
|
|
202
245
|
}
|
|
@@ -7,8 +7,10 @@ export class VideoAgentScene {
|
|
|
7
7
|
scene = new THREE.Scene()
|
|
8
8
|
camera = new THREE.OrthographicCamera(-240, 240, 135, -135)
|
|
9
9
|
renderer = new THREE.WebGLRenderer({ alpha: true })
|
|
10
|
+
container: HTMLElement
|
|
10
11
|
|
|
11
12
|
constructor(container: HTMLElement, needRender = true) {
|
|
13
|
+
this.container = container
|
|
12
14
|
this.camera.position.set(0, 0, 10)
|
|
13
15
|
this.camera.lookAt(0, 0, 0)
|
|
14
16
|
const state = {
|
|
@@ -35,4 +37,8 @@ export class VideoAgentScene {
|
|
|
35
37
|
}
|
|
36
38
|
requestAnimationFrame(this.run)
|
|
37
39
|
}
|
|
40
|
+
|
|
41
|
+
dispose = () => {
|
|
42
|
+
this.videoAgentMesh?.dispose()
|
|
43
|
+
}
|
|
38
44
|
}
|
|
@@ -14,6 +14,11 @@ export function VideoAgent(props: { onClick?: () => void }) {
|
|
|
14
14
|
}
|
|
15
15
|
const videoAgentScene = new VideoAgentScene(ref.current)
|
|
16
16
|
controller.videoAgentScene = videoAgentScene
|
|
17
|
+
|
|
18
|
+
return () => {
|
|
19
|
+
controller.dispose()
|
|
20
|
+
controller.videoAgentScene?.dispose()
|
|
21
|
+
}
|
|
17
22
|
}, [])
|
|
18
23
|
|
|
19
24
|
return (
|
|
@@ -8,7 +8,20 @@ const VreoContext = React.createContext<Player | null>(null)
|
|
|
8
8
|
export const VreoProvider: React.FC = (props) => {
|
|
9
9
|
const five = unsafe__useFiveInstance()
|
|
10
10
|
|
|
11
|
-
const player =
|
|
11
|
+
const [player, setPlayer] = React.useState<Player | null>(null)
|
|
12
|
+
const playerRef = React.useRef<Player | null>(null)
|
|
13
|
+
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
playerRef.current = new Player(five)
|
|
16
|
+
setPlayer(playerRef.current)
|
|
17
|
+
|
|
18
|
+
return () => {
|
|
19
|
+
playerRef.current?.dispose()
|
|
20
|
+
}
|
|
21
|
+
}, [])
|
|
22
|
+
|
|
23
|
+
if (!player) return <></>
|
|
24
|
+
|
|
12
25
|
return <VreoContext.Provider value={player}>{props.children}</VreoContext.Provider>
|
|
13
26
|
}
|
|
14
27
|
|
|
@@ -78,9 +91,13 @@ export function useVreoEventCallback<T extends keyof VreoKeyframeEvent>(
|
|
|
78
91
|
if (deps !== undefined) {
|
|
79
92
|
dependencyList = dependencyList.concat(deps)
|
|
80
93
|
}
|
|
81
|
-
React.
|
|
94
|
+
React.useEffect(() => {
|
|
82
95
|
// @ts-ignore
|
|
83
|
-
|
|
96
|
+
player.on(name, callback)
|
|
97
|
+
return () => {
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
player.off(name, callback)
|
|
100
|
+
}
|
|
84
101
|
}, dependencyList)
|
|
85
102
|
}
|
|
86
103
|
|