@realsee/vreo 0.2.0-alpha.12 → 0.2.0-alpha.15
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 +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Player.AudioLike.html +52 -0
- package/docs/classes/Player.Controller.html +3 -3
- package/docs/classes/Player.Player-1.html +3 -3
- package/docs/classes/Player.VideoAgentMesh.html +12 -12
- package/docs/classes/Player.VideoAgentScene.html +1 -1
- package/docs/demo/assets/AppReact.0de930ef.js +1 -0
- package/docs/demo/assets/default.34811e91.js +64 -0
- package/docs/demo/assets/default.70243c83.css +1 -0
- package/docs/demo/assets/dynamic.e9ba8b28.js +1 -0
- package/docs/demo/assets/examples.5b87fcb8.js +25 -0
- package/docs/demo/assets/examples.dac4a6fe.css +1 -0
- package/docs/demo/assets/index.863d264e.js +1 -0
- package/docs/demo/assets/index.a7bafdff.css +1 -0
- package/docs/demo/assets/main.09d23dce.js +1 -0
- package/docs/demo/assets/react.aa3cf7f7.css +1 -0
- package/docs/demo/assets/react.b5f48ad5.js +25 -0
- package/docs/demo/assets/vendor.f4c5cb32.js +3902 -0
- package/docs/demo/assets/znRoyv06SZQeqA7m.0057e8ae.js +1 -0
- package/docs/demo/examples.html +18 -0
- package/docs/demo/index-react-dynamic.html +21 -0
- package/docs/demo/index-react.html +21 -0
- package/docs/demo/index.html +20 -0
- 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.PanoTagStyleEnum.html +2 -2
- 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 +1 -1
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -1
- package/docs/interfaces/Player.PlayerConfigs.html +2 -2
- 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.CSS3DRenderPluginExportType.html +4 -0
- 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/fivePlugins.Vector3Position.html +3 -0
- package/docs/interfaces/react.VreoActionCallbacks.html +6 -6
- package/docs/interfaces/react.VreoProviderProps.html +1 -1
- package/docs/modules/Player.html +18 -14
- package/docs/modules/custom.html +1 -1
- package/docs/modules/fivePlugins.html +5 -2
- package/docs/modules/react.html +1 -1
- package/lib/Player/Controller.d.ts +1 -1
- package/lib/Player/custom/SpatialScenePanel/index.js +2 -2
- package/lib/Player/index.js +9 -15
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +4 -2
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +67 -21
- package/lib/Player/modules/VideoAgent/VideoAgentScene.js +2 -1
- package/lib/Player/modules/keyframes/PanoTextLabel/index.d.ts +3 -0
- package/lib/Player/modules/keyframes/PanoTextLabel/index.js +96 -43
- package/lib/fivePlugins/CSS3DRenderPlugin/centerPoint.d.ts +2 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/centerPoint.js +12 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/createResizeObserver.d.ts +7 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/createResizeObserver.js +32 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/evenNumber.d.ts +3 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/evenNumber.js +11 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/index.d.ts +56 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/index.js +275 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/transformPositionToVector3.d.ts +7 -0
- package/lib/fivePlugins/CSS3DRenderPlugin/transformPositionToVector3.js +18 -0
- package/lib/shared-utils/AduioLike.d.ts +37 -0
- package/lib/shared-utils/AduioLike.js +165 -0
- package/lib/typings/VreoUnit.d.ts +11 -0
- package/package.json +2 -2
- package/resources/Player/Controller.ts +2 -0
- package/resources/Player/custom/SpatialScenePanel/index.tsx +4 -4
- package/resources/Player/index.tsx +38 -28
- package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +37 -7
- package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +2 -0
- package/resources/Player/modules/keyframes/PanoTextLabel/index.tsx +87 -34
- package/resources/fivePlugins/CSS3DRenderPlugin/centerPoint.ts +5 -0
- package/resources/fivePlugins/CSS3DRenderPlugin/createResizeObserver.ts +17 -0
- package/resources/fivePlugins/CSS3DRenderPlugin/evenNumber.ts +4 -0
- package/resources/fivePlugins/CSS3DRenderPlugin/index.ts +254 -0
- package/resources/fivePlugins/CSS3DRenderPlugin/transformPositionToVector3.ts +5 -0
- package/resources/shared-utils/AduioLike.ts +108 -0
- package/resources/typings/VreoUnit.ts +13 -1
- package/stylesheets/default.css +5 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports["default"] = exports.AudioLike = void 0;
|
|
9
|
+
|
|
10
|
+
var _five = require("@realsee/five");
|
|
11
|
+
|
|
12
|
+
var _animationFrame = require("./animationFrame");
|
|
13
|
+
|
|
14
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
15
|
+
|
|
16
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
17
|
+
|
|
18
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
19
|
+
|
|
20
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
21
|
+
|
|
22
|
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
23
|
+
|
|
24
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
25
|
+
|
|
26
|
+
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
|
|
27
|
+
|
|
28
|
+
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
29
|
+
|
|
30
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
31
|
+
|
|
32
|
+
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
33
|
+
|
|
34
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 模拟 `<Audio>` 功能:没有音频,但执行逻辑跟 `<Audio>` 相似。
|
|
38
|
+
*/
|
|
39
|
+
var AudioLike = /*#__PURE__*/function (_Subscribe) {
|
|
40
|
+
_inherits(AudioLike, _Subscribe);
|
|
41
|
+
|
|
42
|
+
var _super = _createSuper(AudioLike);
|
|
43
|
+
|
|
44
|
+
function AudioLike() {
|
|
45
|
+
var _this;
|
|
46
|
+
|
|
47
|
+
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
48
|
+
duration = _ref.duration;
|
|
49
|
+
|
|
50
|
+
_classCallCheck(this, AudioLike);
|
|
51
|
+
|
|
52
|
+
_this = _super.call(this);
|
|
53
|
+
|
|
54
|
+
_defineProperty(_assertThisInitialized(_this), "$timestamp", 0);
|
|
55
|
+
|
|
56
|
+
_defineProperty(_assertThisInitialized(_this), "$currentTime", 0);
|
|
57
|
+
|
|
58
|
+
_defineProperty(_assertThisInitialized(_this), "$duration", 0);
|
|
59
|
+
|
|
60
|
+
_defineProperty(_assertThisInitialized(_this), "muted", false);
|
|
61
|
+
|
|
62
|
+
_defineProperty(_assertThisInitialized(_this), "src", '');
|
|
63
|
+
|
|
64
|
+
if (duration) {
|
|
65
|
+
_this.$duration = duration;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return _this;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_createClass(AudioLike, [{
|
|
72
|
+
key: "setAttribute",
|
|
73
|
+
value: function setAttribute(name, value) {// nothing todo
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
key: "play",
|
|
77
|
+
value: function play() {
|
|
78
|
+
var _this2 = this;
|
|
79
|
+
|
|
80
|
+
if (this.$timestamp === 0) {
|
|
81
|
+
this.$timestamp = performance.now();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.$currentTime === this.$duration) {
|
|
85
|
+
this.$currentTime = 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.stopInterval = (0, _animationFrame.requestAnimationFrameInterval)(function () {
|
|
89
|
+
return _this2.requestAnimationFrameLoop();
|
|
90
|
+
});
|
|
91
|
+
this.emit('play');
|
|
92
|
+
}
|
|
93
|
+
}, {
|
|
94
|
+
key: "pause",
|
|
95
|
+
value: function pause() {
|
|
96
|
+
if (this.stopInterval) {
|
|
97
|
+
this.stopInterval();
|
|
98
|
+
this.emit('pause');
|
|
99
|
+
this.stopInterval = undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.$timestamp = 0;
|
|
103
|
+
}
|
|
104
|
+
}, {
|
|
105
|
+
key: "requestAnimationFrameLoop",
|
|
106
|
+
value: function requestAnimationFrameLoop() {
|
|
107
|
+
var now = performance.now();
|
|
108
|
+
this.$currentTime = now - this.$timestamp;
|
|
109
|
+
this.emit('timeupdate');
|
|
110
|
+
|
|
111
|
+
if (this.$currentTime >= this.$duration - 10) {
|
|
112
|
+
this.$currentTime = this.$duration;
|
|
113
|
+
this.pause();
|
|
114
|
+
this.emit('ended');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, {
|
|
118
|
+
key: "currentTime",
|
|
119
|
+
get: function get() {
|
|
120
|
+
return this.$currentTime / 1000;
|
|
121
|
+
},
|
|
122
|
+
set: function set(time) {
|
|
123
|
+
this.$currentTime = time;
|
|
124
|
+
}
|
|
125
|
+
}, {
|
|
126
|
+
key: "duration",
|
|
127
|
+
get: function get() {
|
|
128
|
+
return this.$duration;
|
|
129
|
+
},
|
|
130
|
+
set: function set(duration) {
|
|
131
|
+
this.pause();
|
|
132
|
+
this.$duration = duration;
|
|
133
|
+
this.$timestamp = 0;
|
|
134
|
+
this.$currentTime = 0;
|
|
135
|
+
}
|
|
136
|
+
}, {
|
|
137
|
+
key: "ended",
|
|
138
|
+
get: function get() {
|
|
139
|
+
return this.$currentTime === this.$duration;
|
|
140
|
+
}
|
|
141
|
+
}, {
|
|
142
|
+
key: "paused",
|
|
143
|
+
get: function get() {
|
|
144
|
+
return !this.stopInterval;
|
|
145
|
+
}
|
|
146
|
+
}, {
|
|
147
|
+
key: "addEventListener",
|
|
148
|
+
value: function addEventListener(evtName, callback) {
|
|
149
|
+
var useCapture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
150
|
+
this.on(evtName, callback);
|
|
151
|
+
}
|
|
152
|
+
}, {
|
|
153
|
+
key: "removeEventListener",
|
|
154
|
+
value: function removeEventListener(evtName, callback) {
|
|
155
|
+
var useCapture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
156
|
+
this.off(evtName, callback);
|
|
157
|
+
}
|
|
158
|
+
}]);
|
|
159
|
+
|
|
160
|
+
return AudioLike;
|
|
161
|
+
}(_five.Subscribe);
|
|
162
|
+
|
|
163
|
+
exports.AudioLike = AudioLike;
|
|
164
|
+
var _default = AudioLike;
|
|
165
|
+
exports["default"] = _default;
|
|
@@ -172,12 +172,23 @@ export declare type ModelVideoData = {
|
|
|
172
172
|
vertexs: QuadrangleVertexs | Vertexs;
|
|
173
173
|
matrixWorld?: number[];
|
|
174
174
|
};
|
|
175
|
+
/**
|
|
176
|
+
* 四元数
|
|
177
|
+
*/
|
|
178
|
+
export declare type Quaternion = {
|
|
179
|
+
x: number;
|
|
180
|
+
y: number;
|
|
181
|
+
z: number;
|
|
182
|
+
w: number;
|
|
183
|
+
};
|
|
175
184
|
/**
|
|
176
185
|
* 全景文本标签
|
|
177
186
|
*/
|
|
178
187
|
export declare type PanoTextLabelData = {
|
|
179
188
|
text: string;
|
|
180
189
|
vertex: Vertex;
|
|
190
|
+
normal?: Vertex;
|
|
191
|
+
quaternion?: Quaternion;
|
|
181
192
|
fontSize?: number;
|
|
182
193
|
};
|
|
183
194
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realsee/vreo",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.15",
|
|
4
4
|
"description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realsee",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dev": "vite --port=3088 --host 0.0.0.0",
|
|
22
22
|
"build": "tsc && vite build",
|
|
23
23
|
"preview": "vite preview",
|
|
24
|
-
"docs": "npx typedoc",
|
|
24
|
+
"docs": "npx typedoc && yarn run build",
|
|
25
25
|
"packages": "node ./dev-tools/build-packages.js"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
@@ -114,12 +114,14 @@ export class Controller extends Subscribe<VreoKeyframeEvent> {
|
|
|
114
114
|
this.videoInstance.pause()
|
|
115
115
|
return
|
|
116
116
|
}
|
|
117
|
+
|
|
117
118
|
if (!this.playing) {
|
|
118
119
|
if (!this.videoInstance?.paused) {
|
|
119
120
|
this.videoInstance?.pause()
|
|
120
121
|
}
|
|
121
122
|
return
|
|
122
123
|
}
|
|
124
|
+
|
|
123
125
|
if (this.videoInstance?.paused && this.playing) {
|
|
124
126
|
this.videoInstance.play()
|
|
125
127
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import ReactDOM from 'react-dom'
|
|
3
3
|
import { Five } from '@realsee/five'
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { CSS3DRenderPlugin, CSS3DRenderPluginExportType } from '@realsee/dnalogel/plugins/CSS3DRenderPlugin'
|
|
4
|
+
import { Raycaster, Vector3 } from 'three'
|
|
5
|
+
import { tweenProgress } from '../../../shared-utils/animationFrame/BetterTween'
|
|
6
|
+
import { CSS3DRenderPlugin, CSS3DRenderPluginExportType } from '../../../fivePlugins/CSS3DRenderPlugin'
|
|
8
7
|
|
|
9
8
|
import { VreoKeyframe, VreoKeyframeEnum } from '../../../typings/VreoUnit'
|
|
10
9
|
import { CustomVreoKeyframeProps } from '../../typings'
|
|
@@ -33,6 +32,7 @@ import { CustomVreoKeyframeProps } from '../../typings'
|
|
|
33
32
|
// "temperature": "27",
|
|
34
33
|
// "title": "沉浸式回家"
|
|
35
34
|
// }
|
|
35
|
+
|
|
36
36
|
export interface SpatialScenePanelData {
|
|
37
37
|
customType: 'SpatialScenePanel'
|
|
38
38
|
title: string
|
|
@@ -91,47 +91,56 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
91
91
|
|
|
92
92
|
// 预载逻辑
|
|
93
93
|
// 是否降低图片分辨率
|
|
94
|
-
if (
|
|
94
|
+
if (
|
|
95
|
+
this.$five.imageOptions.size &&
|
|
96
|
+
this.configs.imageOptions?.size &&
|
|
97
|
+
this.$five.imageOptions.size > this.configs.imageOptions.size
|
|
98
|
+
) {
|
|
95
99
|
this.$five.imageOptions.size = this.configs.imageOptions.size
|
|
96
100
|
}
|
|
97
|
-
|
|
101
|
+
|
|
98
102
|
// 预载数据中的点位
|
|
99
103
|
if (preload || (preload === undefined && this.configs.autoPreload)) {
|
|
100
|
-
const panoIndexMap = vreoUnit.keyframes
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
104
|
+
const panoIndexMap = vreoUnit.keyframes
|
|
105
|
+
.filter((vreoKeyframe) => {
|
|
106
|
+
if (vreoKeyframe.type !== VreoKeyframeEnum.CameraMovement) {
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const data = vreoKeyframe.data as CameraMovementData
|
|
111
|
+
if (data.panoIndex === undefined) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
return true
|
|
115
|
+
})
|
|
116
|
+
.reduce((accu: Record<number, boolean>, curr) => {
|
|
117
|
+
const panoIndex = curr.data.panoIndex as number
|
|
118
|
+
if (!accu[panoIndex]) {
|
|
119
|
+
accu[panoIndex] = true
|
|
120
|
+
}
|
|
121
|
+
return accu
|
|
122
|
+
}, {})
|
|
123
|
+
|
|
118
124
|
const panoIndexs = Object.keys(panoIndexMap)
|
|
119
125
|
for (let i = 0; i < panoIndexs.length; i++) {
|
|
120
126
|
await this.$five.preloadPano(Number(panoIndexs[i]))
|
|
121
127
|
}
|
|
122
128
|
}
|
|
123
|
-
|
|
129
|
+
|
|
124
130
|
// 新数据载入就绪
|
|
125
131
|
this.emit('loaded', vreoUnit)
|
|
126
132
|
this.controller.emit('loaded', vreoUnit)
|
|
127
133
|
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
131
|
-
}
|
|
132
|
-
await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url, currentTime / 1000)
|
|
133
|
-
this.play()
|
|
134
|
+
if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
|
|
135
|
+
this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
134
136
|
}
|
|
137
|
+
await this.controller.videoAgentScene?.videoAgentMesh.play(
|
|
138
|
+
vreoUnit.video.url,
|
|
139
|
+
currentTime / 1000,
|
|
140
|
+
vreoUnit.video.duration
|
|
141
|
+
)
|
|
142
|
+
this.play()
|
|
143
|
+
|
|
135
144
|
this.controller.run((type, keyframe) => this.emit(type, keyframe))
|
|
136
145
|
return true
|
|
137
146
|
}
|
|
@@ -143,9 +152,10 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
|
143
152
|
play(currentTime?: number) {
|
|
144
153
|
if (this.controller.playing) return true
|
|
145
154
|
if (currentTime && this.controller.videoInstance) {
|
|
146
|
-
// Object.assign(window, {$vreoController: this.controller})
|
|
147
155
|
this.controller.videoInstance.currentTime = currentTime / 1000
|
|
148
156
|
}
|
|
157
|
+
Object.assign(window, {$vreoController: this.controller})
|
|
158
|
+
|
|
149
159
|
this.controller.setPlaying(true)
|
|
150
160
|
return true
|
|
151
161
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as THREE from 'three'
|
|
2
2
|
import { Preloader } from '../../../shared-utils/Preloader'
|
|
3
3
|
import { makeObservable, observable, runInAction } from 'mobx'
|
|
4
|
+
import AudioLike from '../../../shared-utils/AduioLike'
|
|
4
5
|
|
|
5
6
|
const vertexShader = `
|
|
6
7
|
varying vec2 vUv;
|
|
@@ -76,14 +77,21 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
76
77
|
freeze: boolean
|
|
77
78
|
paused: boolean
|
|
78
79
|
audioInstance: HTMLAudioElement
|
|
80
|
+
audioLikeInstance: AudioLike
|
|
79
81
|
$removeEventListener: () => void
|
|
80
82
|
|
|
81
|
-
get videoInstance(): HTMLAudioElement {
|
|
83
|
+
get videoInstance(): HTMLAudioElement | AudioLike {
|
|
84
|
+
if (!this.videoUrl) {
|
|
85
|
+
return this.audioLikeInstance
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
if (this.videoUrl?.endsWith('mp3')) {
|
|
83
89
|
return this.audioInstance
|
|
84
90
|
}
|
|
91
|
+
|
|
85
92
|
const uniforms = (this.material as THREE.ShaderMaterial).uniforms
|
|
86
93
|
const videoInstance = uniforms.map.value.image as HTMLVideoElement
|
|
94
|
+
|
|
87
95
|
return videoInstance
|
|
88
96
|
}
|
|
89
97
|
|
|
@@ -155,23 +163,33 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
155
163
|
this.audioInstance = options.audioInstance
|
|
156
164
|
}
|
|
157
165
|
|
|
166
|
+
this.audioLikeInstance = new AudioLike()
|
|
167
|
+
|
|
158
168
|
makeObservable(this, { paused: observable })
|
|
159
169
|
|
|
160
170
|
const updatePaused = (paused: boolean) => runInAction(() => (this.paused = paused))
|
|
161
171
|
const onPause = () => updatePaused(true)
|
|
162
172
|
const onPlay = () => updatePaused(false)
|
|
163
173
|
|
|
164
|
-
this.
|
|
165
|
-
this.
|
|
174
|
+
this.audioInstance.addEventListener('pause', onPause)
|
|
175
|
+
this.audioInstance.addEventListener('play', onPlay)
|
|
176
|
+
this.options.videoInstance?.addEventListener('pause', onPause)
|
|
177
|
+
this.options.videoInstance?.addEventListener('play', onPlay)
|
|
178
|
+
this.audioLikeInstance.addEventListener('pause', onPause)
|
|
179
|
+
this.audioLikeInstance.addEventListener('play', onPlay)
|
|
166
180
|
|
|
167
181
|
this.$removeEventListener = () => {
|
|
168
|
-
this.
|
|
169
|
-
this.
|
|
182
|
+
this.audioInstance.removeEventListener('pause', onPause)
|
|
183
|
+
this.audioInstance.removeEventListener('play', onPlay)
|
|
184
|
+
this.options.videoInstance?.removeEventListener('pause', onPause)
|
|
185
|
+
this.options.videoInstance?.removeEventListener('play', onPlay)
|
|
186
|
+
this.audioLikeInstance.removeEventListener('pause', onPause)
|
|
187
|
+
this.audioLikeInstance.removeEventListener('play', onPlay)
|
|
170
188
|
}
|
|
171
189
|
}
|
|
172
190
|
|
|
173
|
-
|
|
174
191
|
private async update(videoUrl: string) {
|
|
192
|
+
|
|
175
193
|
if (this.videoUrl === videoUrl) {
|
|
176
194
|
return
|
|
177
195
|
}
|
|
@@ -191,19 +209,31 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
191
209
|
this.videoInstance.muted = false
|
|
192
210
|
uniforms.enable.value = this.videoUrl?.endsWith('.mp4') ? 1 : 0
|
|
193
211
|
this.videoInstance.removeEventListener('timeupdate', onStart, false)
|
|
212
|
+
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
this.videoInstance.addEventListener('timeupdate', onStart, false)
|
|
197
216
|
}
|
|
198
217
|
|
|
199
|
-
async play(videoUrl = '', currentTime = 0) {
|
|
218
|
+
async play(videoUrl = '', currentTime = 0, duration?: number) {
|
|
200
219
|
videoUrl = videoUrl || ''
|
|
220
|
+
if (duration && !videoUrl) {
|
|
221
|
+
if (this.currentTime) {
|
|
222
|
+
this.videoInstance.currentTime = currentTime
|
|
223
|
+
}
|
|
224
|
+
(this.videoInstance as AudioLike).duration = duration
|
|
225
|
+
this.videoUrl = ''
|
|
226
|
+
this.videoInstance.play()
|
|
227
|
+
return true
|
|
228
|
+
}
|
|
229
|
+
|
|
201
230
|
if (!videoUrl) {
|
|
202
231
|
if (this.videoUrl) await this.videoInstance.play()
|
|
203
232
|
else console.warn('警告:视频资源未初始化。')
|
|
204
233
|
return true
|
|
205
234
|
}
|
|
206
235
|
|
|
236
|
+
console.log('play', videoUrl, this.videoUrl)
|
|
207
237
|
if (videoUrl === this.videoUrl) {
|
|
208
238
|
this.videoInstance.currentTime = currentTime
|
|
209
239
|
await this.videoInstance.play()
|
|
@@ -33,6 +33,8 @@ export class VideoAgentScene {
|
|
|
33
33
|
run = () => {
|
|
34
34
|
const domElement = this.renderer.domElement
|
|
35
35
|
|
|
36
|
+
// console.log('renderder', this.videoAgentMesh.paused, this.videoAgentMesh.freeze)
|
|
37
|
+
|
|
36
38
|
// 视频开始 1s 不渲染:规避某些设备黑屏闪烁问题。视频前 2s 是最好是静默的。
|
|
37
39
|
if (!(this.videoAgentMesh.paused || this.videoAgentMesh.freeze) && this.videoAgentMesh.currentTime > 1000) {
|
|
38
40
|
this.renderer.render(this.scene, this.camera)
|
|
@@ -1,21 +1,66 @@
|
|
|
1
|
-
import classNames from 'classnames'
|
|
2
1
|
import * as React from 'react'
|
|
3
|
-
import
|
|
2
|
+
import * as THREE from 'three'
|
|
3
|
+
import ReactDOM from 'react-dom'
|
|
4
|
+
import { Vector3, Quaternion } from 'three'
|
|
5
|
+
|
|
6
|
+
import { useController, useFiveInstance } from '../../../hooks'
|
|
7
|
+
import { CSS3DRenderPlugin } from '../../../../fivePlugins/CSS3DRenderPlugin'
|
|
4
8
|
import { PanoTextLabelData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
|
|
5
|
-
import { useController, useFiveProject2d } from '../../../hooks'
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 通过传入中心点确定矩形框架容器的四个点:
|
|
12
|
+
* 1. 已知矩形长宽和中心点
|
|
13
|
+
* 2. 借助planeGeometry生成垂直相机视角的平面上的四个点
|
|
14
|
+
* 3. 通过向量相加,平行四边形法则获取到移动position后的面上四个点
|
|
15
|
+
*/
|
|
16
|
+
const calcPoints = (
|
|
17
|
+
centerPoint: Vector3,
|
|
18
|
+
normal: THREE.Vector3 | undefined,
|
|
19
|
+
wrapperLength: number,
|
|
20
|
+
wrapperWidth: number
|
|
21
|
+
) => {
|
|
22
|
+
// 375px 对应 1m
|
|
23
|
+
const length = wrapperLength / 375
|
|
24
|
+
const width = wrapperWidth / 375
|
|
25
|
+
|
|
26
|
+
const geometry = new THREE.PlaneGeometry(length, width)
|
|
27
|
+
if (normal) {
|
|
28
|
+
const lookPoint = new THREE.Vector3(normal.x + centerPoint.x, normal.y + centerPoint.y, normal.z + centerPoint.z)
|
|
29
|
+
geometry.lookAt(lookPoint)
|
|
30
|
+
}
|
|
31
|
+
// const pointgeometry = new THREE.Geometry()
|
|
32
|
+
// pointgeometry.vertices.push(cameraPosition)
|
|
33
|
+
// const pointmaterial = new THREE.PointsMaterial({
|
|
34
|
+
// color: 0xffffff,
|
|
35
|
+
// size: 0.4,
|
|
36
|
+
// })
|
|
37
|
+
// _point = new THREE.Points(pointgeometry, pointmaterial)
|
|
38
|
+
// console.log(cameraPosition)
|
|
39
|
+
|
|
40
|
+
const material = new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide })
|
|
41
|
+
const plane = new THREE.Mesh(geometry, material)
|
|
42
|
+
const v0 = centerPoint.clone()
|
|
43
|
+
plane.position.copy(v0)
|
|
44
|
+
|
|
45
|
+
// 计算传入的四个点的坐标
|
|
46
|
+
const [v1, v2, v3, v4] = plane.geometry.vertices
|
|
47
|
+
const downLeft = v0.clone().add(v4)
|
|
48
|
+
const downRight = v0.clone().add(v3)
|
|
49
|
+
const upLeft = v0.clone().add(v2)
|
|
50
|
+
const upRight = v0.clone().add(v1)
|
|
51
|
+
|
|
52
|
+
// 插件使用要求:矩形四个点位数据,顺序为**必须**为左下、右下、右上、左上
|
|
53
|
+
return [downLeft, downRight, upRight, upLeft]
|
|
12
54
|
}
|
|
13
55
|
|
|
56
|
+
/**
|
|
57
|
+
* 空间文本标签。
|
|
58
|
+
*/
|
|
14
59
|
export function PanoTextLabel() {
|
|
15
|
-
const [state, setState] = React.useState<PanoTextLabelState | null>(null)
|
|
16
60
|
const timeoutRef = React.useRef<NodeJS.Timeout | null>()
|
|
17
61
|
const controller = useController()
|
|
18
|
-
const
|
|
62
|
+
const five = useFiveInstance()
|
|
63
|
+
const ref = React.useRef<ReturnType<typeof CSS3DRenderPlugin>>()
|
|
19
64
|
|
|
20
65
|
React.useEffect(() => {
|
|
21
66
|
if (controller.configs?.keyframeMap.PanoTextLabel === false) {
|
|
@@ -24,19 +69,43 @@ export function PanoTextLabel() {
|
|
|
24
69
|
const callback = (keyframe: VreoKeyframe) => {
|
|
25
70
|
const { start, end, data } = keyframe
|
|
26
71
|
const panoTextLabelData = data as PanoTextLabelData
|
|
72
|
+
// 增加无文本情况的判断
|
|
73
|
+
if (data.text === '') return
|
|
74
|
+
|
|
27
75
|
const { x, y, z } = panoTextLabelData.vertex
|
|
76
|
+
const centerPoint = new Vector3(x, y, z)
|
|
77
|
+
const normal = new Vector3(panoTextLabelData.normal?.x, panoTextLabelData.normal?.y, panoTextLabelData.normal?.z)
|
|
78
|
+
// 生成传入的四个点,将文本框最大宽度定在200px,最高高度在30px
|
|
79
|
+
const wrapperLength = 200
|
|
80
|
+
const wrapperWidth = 30
|
|
81
|
+
const points = calcPoints(centerPoint, panoTextLabelData.normal && normal, wrapperLength, wrapperWidth)
|
|
28
82
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
83
|
+
if (!ref.current) ref.current = CSS3DRenderPlugin(five)
|
|
84
|
+
const container = ref.current.create3DDomContainer(points)
|
|
85
|
+
const css3DObject = container?.css3DObject
|
|
86
|
+
// 将获取的mesh进行旋转操作,根据欧拉角去进行mesh的变换
|
|
87
|
+
if (data.quaternion) {
|
|
88
|
+
const quaternion = new Quaternion(data.quaternion.x, data.quaternion.y, data.quaternion.z, data.quaternion.w)
|
|
89
|
+
css3DObject?.quaternion.copy(quaternion)
|
|
90
|
+
}
|
|
91
|
+
if (container?.container)
|
|
92
|
+
ReactDOM.render(
|
|
93
|
+
<div className="PanoTextLabel PanoTextLabel--notHidden">
|
|
94
|
+
<div className="PanoTextLabel-wrapper">
|
|
95
|
+
<div style={{ fontSize: `${data.fontSize || 16}px` }} className="PanoText-innerText">
|
|
96
|
+
{data.text || ''}
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>,
|
|
100
|
+
container?.container
|
|
101
|
+
)
|
|
32
102
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
103
|
+
timeoutRef.current = setTimeout(() => {
|
|
104
|
+
ref.current?.disposeAll()
|
|
105
|
+
}, end - start)
|
|
36
106
|
}
|
|
37
107
|
controller.on(VreoKeyframeEnum.PanoTextLabel, callback)
|
|
38
108
|
|
|
39
|
-
// Object.assign(window, { $panoTextLabel: { setState } })
|
|
40
109
|
return () => {
|
|
41
110
|
controller.off(VreoKeyframeEnum.PanoTextLabel, callback)
|
|
42
111
|
if (timeoutRef.current) {
|
|
@@ -45,21 +114,5 @@ export function PanoTextLabel() {
|
|
|
45
114
|
}
|
|
46
115
|
}, [controller])
|
|
47
116
|
|
|
48
|
-
return
|
|
49
|
-
<div
|
|
50
|
-
className={classNames('PanoTextLabel', {
|
|
51
|
-
'PanoTextLabel--notHidden': state,
|
|
52
|
-
})}
|
|
53
|
-
style={{
|
|
54
|
-
left: (state?.left || 0) + 'px',
|
|
55
|
-
top: (state?.top || 0) + 'px',
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
<div className="PanoTextLabel-wrapper">
|
|
59
|
-
<div style={{ fontSize: `${state?.fontSize || 16}px` }} className="PanoText-innerText">
|
|
60
|
-
{state?.text || ''}
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
)
|
|
117
|
+
return <></>
|
|
65
118
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 简陋的 ResizeObserver polyfill
|
|
3
|
+
*/
|
|
4
|
+
export default function createResizeObserver(func: () => any, element?: HTMLElement) {
|
|
5
|
+
if (!element || typeof ResizeObserver === 'undefined') {
|
|
6
|
+
return {
|
|
7
|
+
observe: () => window.addEventListener('resize', func),
|
|
8
|
+
unobserve: () => window.removeEventListener('resize', func),
|
|
9
|
+
}
|
|
10
|
+
} else {
|
|
11
|
+
const observer = new ResizeObserver(func)
|
|
12
|
+
return {
|
|
13
|
+
observe: () => observer.observe(element),
|
|
14
|
+
unobserve: () => observer.unobserve(element),
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|