@realsee/vreo 0.2.0-alpha.7 → 0.2.0-alpha.8

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.
Files changed (56) hide show
  1. package/README.md +27 -0
  2. package/docs/assets/search.js +1 -1
  3. package/docs/classes/Player.Controller.html +3 -3
  4. package/docs/classes/Player.Player-1.html +3 -3
  5. package/docs/classes/Player.VideoAgentMesh.html +11 -11
  6. package/docs/classes/Player.VideoAgentScene.html +1 -1
  7. package/docs/enums/Player.InfoPanelStyleEnum.html +1 -1
  8. package/docs/enums/Player.InfoPanelTypeEnum.html +1 -1
  9. package/docs/enums/Player.PanoEffectEnum.html +1 -1
  10. package/docs/enums/Player.PanoTagEnum.html +1 -1
  11. package/docs/enums/Player.VreoKeyframeEnum.html +12 -12
  12. package/docs/enums/fivePlugins.CameraMovementEffect.html +1 -1
  13. package/docs/enums/fivePlugins.Rotation.html +1 -1
  14. package/docs/index.html +20 -0
  15. package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -1
  16. package/docs/interfaces/Player.PlayerConfigs.html +3 -3
  17. package/docs/interfaces/Player.Vertex.html +1 -1
  18. package/docs/interfaces/Player.VideoAgentMeshOptions.html +1 -1
  19. package/docs/interfaces/Player.VreoKeyframe.html +1 -1
  20. package/docs/interfaces/Player.VreoUnit.html +1 -1
  21. package/docs/interfaces/Player.VreoVideo.html +1 -1
  22. package/docs/interfaces/fivePlugins.CameraMovementOptsCallback.html +1 -1
  23. package/docs/interfaces/fivePlugins.CameraMovementPluginExportType.html +2 -2
  24. package/docs/interfaces/fivePlugins.ModelTVVideoPluginData.html +1 -1
  25. package/docs/interfaces/fivePlugins.ModelTVVideoPluginExportType.html +1 -1
  26. package/docs/interfaces/fivePlugins.ModelTVVideoPluginParameterType.html +1 -1
  27. package/docs/interfaces/react.VreoActionCallbacks.html +6 -6
  28. package/docs/interfaces/react.VreoProviderProps.html +1 -1
  29. package/docs/modules/Player.html +13 -13
  30. package/docs/modules/custom.html +1 -1
  31. package/docs/modules/fivePlugins.html +2 -2
  32. package/docs/modules/react.html +1 -1
  33. package/lib/PlayController/createHTMLAudioElement.d.ts +1 -0
  34. package/lib/PlayController/createHTMLAudioElement.js +47 -0
  35. package/lib/PlayController/index.d.ts +38 -0
  36. package/lib/PlayController/index.js +300 -0
  37. package/lib/Player/custom/SpatialScenePanel/index.js +0 -1
  38. package/lib/Player/index.d.ts +1 -1
  39. package/lib/Player/index.js +68 -9
  40. package/lib/Player/modules/keyframes/CameraMovement/index.js +41 -5
  41. package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +23 -15
  42. package/lib/Player/typings.d.ts +4 -0
  43. package/lib/fivePlugins/CameraMovementPlugin/index.js +101 -90
  44. package/lib/fivePlugins/CameraMovementPlugin/typings.d.ts +3 -2
  45. package/lib/typings/VreoUnit.d.ts +4 -3
  46. package/package.json +1 -1
  47. package/resources/PlayController/createHTMLAudioElement.ts +53 -0
  48. package/resources/PlayController/index.ts +167 -0
  49. package/resources/Player/custom/SpatialScenePanel/index.tsx +0 -1
  50. package/resources/Player/index.tsx +34 -2
  51. package/resources/Player/modules/keyframes/CameraMovement/index.tsx +7 -3
  52. package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +20 -15
  53. package/resources/Player/typings.ts +2 -0
  54. package/resources/fivePlugins/CameraMovementPlugin/index.ts +55 -47
  55. package/resources/fivePlugins/CameraMovementPlugin/typings.ts +2 -1
  56. package/resources/typings/VreoUnit.ts +5 -4
@@ -54,114 +54,125 @@ function progressNumber(from, to, pst) {
54
54
 
55
55
 
56
56
  var CameraMovementPlugin = function CameraMovementPlugin(five) {
57
- var move = /*#__PURE__*/function () {
58
- var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(args, duration) {
59
- var opts,
60
- _args = arguments;
61
- return regeneratorRuntime.wrap(function _callee$(_context) {
62
- while (1) {
63
- switch (_context.prev = _context.next) {
64
- case 0:
65
- opts = _args.length > 2 && _args[2] !== undefined ? _args[2] : {
66
- preload: true
67
- };
57
+ var move = function move(args, duration) {
58
+ var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
59
+ preload: true
60
+ };
61
+ return new Promise( /*#__PURE__*/function () {
62
+ var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(resolve, reject) {
63
+ var panoIndex, movePanoOptions;
64
+ return regeneratorRuntime.wrap(function _callee$(_context) {
65
+ while (1) {
66
+ switch (_context.prev = _context.next) {
67
+ case 0:
68
+ if (opts.asyncStartCallback) {
69
+ opts.asyncStartCallback();
70
+ }
68
71
 
69
- if (opts.asyncStartCallback) {
70
- opts.asyncStartCallback();
71
- }
72
+ if (!(five.panoIndex === undefined)) {
73
+ _context.next = 3;
74
+ break;
75
+ }
72
76
 
73
- if (!(args.mode && args.mode !== five.currentMode)) {
74
- _context.next = 5;
75
- break;
76
- }
77
+ return _context.abrupt("return", reject(false));
78
+
79
+ case 3:
80
+ if (!(args.mode && args.mode !== five.currentMode)) {
81
+ _context.next = 6;
82
+ break;
83
+ }
77
84
 
78
- _context.next = 5;
79
- return new Promise(function (resolve) {
80
- if (!args.mode) return;
81
- five.once('modeChange', function (mode) {
82
- five.once('initAnimationEnded', function () {
83
- if (mode === args.mode) {
84
- resolve(true);
85
- }
85
+ _context.next = 6;
86
+ return new Promise(function (resolve) {
87
+ if (!args.mode) return;
88
+ five.once('modeChange', function (mode) {
89
+ five.once('initAnimationEnded', function () {
90
+ if (mode === args.mode) {
91
+ resolve(true);
92
+ }
93
+ });
94
+ });
95
+ five.changeMode(args.mode, {
96
+ fov: args.fov || undefined,
97
+ latitude: args.latitude || undefined,
98
+ longitude: args.longitude || undefined,
99
+ panoIndex: args.panoIndex || undefined
86
100
  });
87
101
  });
88
- five.changeMode(args.mode, {
89
- fov: args.fov || undefined,
90
- latitude: args.latitude || undefined,
91
- longitude: args.longitude || undefined,
92
- panoIndex: args.panoIndex || undefined
93
- });
94
- });
95
102
 
96
- case 5:
97
- if (!(args.mode === _five.Five.Mode.Floorplan)) {
98
- _context.next = 7;
99
- break;
100
- }
103
+ case 6:
104
+ if (!(args.mode === _five.Five.Mode.Floorplan)) {
105
+ _context.next = 8;
106
+ break;
107
+ }
101
108
 
102
- return _context.abrupt("return", true);
109
+ return _context.abrupt("return", resolve(true));
103
110
 
104
- case 7:
105
- if (!(opts.preload && args.panoIndex !== undefined && args.panoIndex !== five.panoIndex)) {
106
- _context.next = 10;
107
- break;
108
- }
111
+ case 8:
112
+ if (!(opts.preload && args.panoIndex !== undefined && args.panoIndex !== five.panoIndex)) {
113
+ _context.next = 11;
114
+ break;
115
+ }
109
116
 
110
- _context.next = 10;
111
- return five.preloadPano(args.panoIndex);
117
+ _context.next = 11;
118
+ return five.preloadPano(args.panoIndex);
112
119
 
113
- case 10:
114
- if (opts.asyncEndCallback) {
115
- opts.asyncEndCallback();
116
- }
120
+ case 11:
121
+ if (opts.asyncEndCallback) {
122
+ opts.asyncEndCallback();
123
+ }
117
124
 
118
- if (!(args.panoIndex === undefined && args.fov === undefined && args.latitude === undefined && args.longitude === undefined)) {
119
- _context.next = 13;
120
- break;
121
- }
125
+ if (!(args.panoIndex === undefined && args.fov === undefined && args.latitude === undefined && args.longitude === undefined)) {
126
+ _context.next = 14;
127
+ break;
128
+ }
122
129
 
123
- return _context.abrupt("return", true);
130
+ return _context.abrupt("return", resolve(true));
124
131
 
125
- case 13:
126
- _context.next = 15;
127
- return new Promise(function (resolve, reject) {
128
- var panoIndex = args.panoIndex !== undefined ? args.panoIndex : five.panoIndex;
129
-
130
- if (panoIndex !== undefined) {
131
- var movePanoOptions = {
132
- duration: duration,
133
- // 移动耗时
134
- moveEndCallback: function moveEndCallback() {
135
- return resolve(true);
136
- },
137
- // 移动结束
138
- moveCancelCallback: function moveCancelCallback() {
139
- return reject(false);
140
- },
141
- // 移动开始
142
- effect: 'fade'
143
- };
144
- five.moveToPano(panoIndex, Object.assign(movePanoOptions, args));
145
- } else {
146
- reject(false);
132
+ case 14:
133
+ panoIndex = args.panoIndex !== undefined ? args.panoIndex : five.panoIndex;
134
+
135
+ if (!(panoIndex !== undefined)) {
136
+ _context.next = 21;
137
+ break;
147
138
  }
148
- });
149
139
 
150
- case 15:
151
- return _context.abrupt("return", _context.sent);
140
+ movePanoOptions = Object.assign(args, {
141
+ duration: duration,
142
+ // 移动耗时
143
+ moveEndCallback: function moveEndCallback() {
144
+ return resolve(true);
145
+ },
146
+ // 移动结束
147
+ moveCancelCallback: function moveCancelCallback() {
148
+ resolve(true);
149
+ } // 移动开始
150
+ // effect: args.transEffect || 'fade',
152
151
 
153
- case 16:
154
- case "end":
155
- return _context.stop();
152
+ });
153
+ _context.next = 19;
154
+ return five.moveToPano(panoIndex, movePanoOptions);
155
+
156
+ case 19:
157
+ _context.next = 22;
158
+ break;
159
+
160
+ case 21:
161
+ reject(false);
162
+
163
+ case 22:
164
+ case "end":
165
+ return _context.stop();
166
+ }
156
167
  }
157
- }
158
- }, _callee);
159
- }));
168
+ }, _callee);
169
+ }));
160
170
 
161
- return function move(_x, _x2) {
162
- return _ref.apply(this, arguments);
163
- };
164
- }();
171
+ return function (_x, _x2) {
172
+ return _ref.apply(this, arguments);
173
+ };
174
+ }());
175
+ };
165
176
 
166
177
  var getAnimeParams = function getAnimeParams(args) {
167
178
  var currentFiveState = five.state; // latitude
@@ -1,4 +1,4 @@
1
- import { Mode, MovePanoOptions, Pose } from '@realsee/five';
1
+ import { Mode, Pose } from '@realsee/five';
2
2
  export interface CameraMovementPluginParameterType {
3
3
  }
4
4
  export interface CameraMovementPluginExportType {
@@ -33,7 +33,8 @@ export interface CameraMovementOptsCallback {
33
33
  export declare type MoveArgs = {
34
34
  mode: Mode;
35
35
  panoIndex: number;
36
- } & Pose & Pick<MovePanoOptions, 'effect'>;
36
+ transEffect?: "fly" | "fade" | "instant";
37
+ } & Pose;
37
38
  export declare type MoveOpts = {
38
39
  preload?: boolean;
39
40
  } & CameraMovementOptsCallback;
@@ -61,7 +61,7 @@ export declare type VreoKeyframeConfigMap = {
61
61
  * 剧本关键帧
62
62
  */
63
63
  export interface VreoKeyframe {
64
- uuid: string;
64
+ uuid?: string;
65
65
  type: VreoKeyframeEnum;
66
66
  start: number;
67
67
  end: number;
@@ -95,7 +95,7 @@ export declare type VreoKeyframeEvent = {
95
95
  [key in VreoKeyframeEnum]: (keyframe: VreoKeyframe) => void;
96
96
  } & {
97
97
  loaded: (vreoUnit: VreoUnit) => void;
98
- paused: () => void;
98
+ paused: (ended?: boolean) => void;
99
99
  playing: () => void;
100
100
  unknownKeyframeType: (keyframe: Record<string, any>) => void;
101
101
  };
@@ -103,7 +103,8 @@ export declare type VreoKeyframeEvent = {
103
103
  * 相机运动
104
104
  */
105
105
  export declare type CameraMovementData = {
106
- effect: CameraMovementEffect;
106
+ effect?: CameraMovementEffect;
107
+ transEffect?: "fly" | "fade" | "instant";
107
108
  mode: Mode;
108
109
  panoIndex: number;
109
110
  loop?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realsee/vreo",
3
- "version": "0.2.0-alpha.7",
3
+ "version": "0.2.0-alpha.8",
4
4
  "description": "Vreo (VR Video 缩写) 是基于如视三维渲染引擎 Five 和 用户界面构建库 React 实现的如视 3D 空间剧本播放器。",
5
5
  "keywords": [
6
6
  "realsee",
@@ -0,0 +1,53 @@
1
+
2
+ const BLANK_AUDIO = ''
3
+ + 'data:audio/mpeg;base64,'
4
+ + '//uQxAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAADAAAGhgBVVVVVVVVVVVVVVVVVVVVVVVV'
5
+ + 'VVVVVVVVVVVVVVVVVVVWqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr///////////'
6
+ + '////////////////////////////////8AAAA5TEFNRTMuOThyAc0AAAAAAAAAABSAJAiqQgAAg'
7
+ + 'AAABobxtI73AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
8
+ + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
9
+ + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
10
+ + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
11
+ + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//uQxAACFEII9ACZ/sJZwWEoEb8w/////N//////Jcxj'
12
+ + 'Hjf+7/v/H2PzCCFAiDtGeyBCIx7bJJ1mmEEMy6g8mm2c8nrGABB4h2Mkmn//4z/73u773R5qHHu'
13
+ + '/j/w7Kxkzh5lWRWdsifCkNAnY9Zc1HvDAhjhSHdFkHFzLmabt/AQxSg2wwzLhHIJOBnAWwVY4zr'
14
+ + 'hIYhhc2kvhYDfQ4hDi2Gmh5KyFn8EcGIrHAngNgIwVIEMf5bzbAiTRoAD///8z/KVhkkWEle6IX'
15
+ + '+d/z4fvH3BShK1e5kmjkCMoxVmXhd4ROlTKo3iipasvTilY21q19ta30/v/0/idPX1v8PNxJL6r'
16
+ + 'amnOVsdvMv2akO0iSYIzdJFirtzWXCZicS9vHqvSKyqm5XJBdqBwPxyfJdykhWTZ0G0ZyTZGpLK'
17
+ + 'xsNwwoRhsx3tZfhwmeOBVISm3impAC/IT/8hP/EKEM1KMdVdVKM2rHV4x7HVXZvbVVKN/qq8CiV'
18
+ + '9VL9jjH/6l6qf7MBCjZmOqsAibjcP+qqqv0oxqpa/NVW286hPo1nz2L/h8+jXt//uSxCmDU2IK/'
19
+ + 'ECN98KKtE5IYzNoCfbw+u9i5r8PoadUMFPKqWL4LK3T/LCraMSHGkW4bpLXR/E6LlHOVQxmslKV'
20
+ + 'J8IULktMN06N0FKCpHCoYsjC4F+Z0NVqdNFoGSTjSiyjzLdnZ2fNqTi2eHKONONKLMPMKLONKLM'
21
+ + 'PQRJGlFxZRoKcJFAYEeIFiRQkUWUeYfef//Ko04soswso40UJAgMw8wosososy0EalnZyjQUGBR'
22
+ + 'QGIFggOWUacWUeYmuadrZziQKKEgQsQLAhQkUJAgMQDghltLO1onp0cpkNInSFMqlYeSEJ5AHsq'
23
+ + 'FdOwy1DA2sRmRJKxdKRfLhfLw5BzUxBTUUzLjk4LjJVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
24
+ + 'VVVVVVVVVVVVVVVVVUxBTUUzLjk4LjJVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
25
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
26
+ + 'VVVVVVVVVVVVVVVVVVVf/7ksRRA8AAAaQAAAAgAAA0gAAABFVVVVVVVVVVVVVVVVVVVVVVVVVVV'
27
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
28
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
29
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
30
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
31
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
32
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
33
+ + 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=';
34
+
35
+
36
+ export function createHTMLAudioElement(): HTMLAudioElement {
37
+ const ndAudio = document.querySelector('#vreo-playController-audio')
38
+ if (ndAudio) {
39
+ return ndAudio as HTMLAudioElement
40
+ }
41
+
42
+ const audio = document.createElement('audio')
43
+ audio.style.display = 'none'
44
+ audio.setAttribute('id', 'vreo-playController-audio')
45
+ audio.controls = false
46
+ document.body.appendChild(audio)
47
+ audio.src = BLANK_AUDIO
48
+
49
+ // 触发一次播放
50
+ Promise.resolve(async () => await audio.play())
51
+
52
+ return audio
53
+ }
@@ -0,0 +1,167 @@
1
+ import { Subscribe } from '@realsee/five'
2
+ import { requestAnimationFrameInterval } from '../shared-utils/animationFrame'
3
+ import { VreoKeyframe, VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
4
+ import { createHTMLAudioElement } from './createHTMLAudioElement'
5
+
6
+ export interface PlayControllerConfig {
7
+ audio?: HTMLAudioElement
8
+ }
9
+
10
+ const closures: Record<string, any> = {}
11
+
12
+ export class PlayController extends Subscribe<VreoKeyframeEvent> {
13
+
14
+ vreoUnit?: VreoUnit
15
+
16
+ config: PlayControllerConfig = {}
17
+ stopInterval: () => void
18
+
19
+ get paused() {
20
+ return this.audioInstance.paused
21
+ }
22
+
23
+ get audioInstance() {
24
+ return this.config.audio!
25
+ }
26
+
27
+ get currentTime() {
28
+ return this.audioInstance.currentTime * 1000
29
+ }
30
+
31
+ get currentKeyframes() {
32
+ if (!this.vreoUnit) return []
33
+ const keyframes = this.vreoUnit.keyframes
34
+ // 没有被解析过且开始时间低于当前时间戳 100ms
35
+ return keyframes.filter((keyframe: VreoKeyframe) => {
36
+ if (keyframe.parsed) return false
37
+ const dur = this.currentTime - keyframe.start
38
+ return dur <= 100 && dur >= 0
39
+ })
40
+ }
41
+
42
+ /**
43
+ * 音频时长 不一定能获取得到,建议以 VreoUnit 配置的时长为准。
44
+ */
45
+ get duration() {
46
+ return this.audioInstance.duration * 1000
47
+ }
48
+
49
+ constructor(config: PlayControllerConfig = {}) {
50
+ super()
51
+
52
+ if (!config.audio) {
53
+ config.audio = createHTMLAudioElement()
54
+ }
55
+
56
+ this.config = Object.assign(this.config, config)
57
+
58
+ closures.onPlaying = () => this.emit('playing')
59
+ closures.onPaused = () => this.emit('paused')
60
+ closures.onEnded = () => this.emit('paused', true)
61
+
62
+ this.audioInstance.addEventListener('play', closures.onPlaying)
63
+ this.audioInstance.addEventListener('pause', closures.onPaused)
64
+ this.audioInstance.addEventListener('ended', closures.onEnded)
65
+
66
+ this.stopInterval = requestAnimationFrameInterval(() => {
67
+ if (this.audioInstance.paused) {
68
+ return
69
+ }
70
+
71
+ if (!this.vreoUnit) {
72
+ return
73
+ }
74
+
75
+ const keyframes = this.vreoUnit.keyframes
76
+ const currentTime = this.currentTime
77
+ // 没有被解析过且开始时间低于当前时间戳 100ms
78
+ const currentKeyframes = keyframes.filter((keyframe: VreoKeyframe) => {
79
+ if (keyframe.parsed) return false
80
+
81
+ const dur = currentTime - keyframe.start
82
+ return dur <= 60 && dur >= 0
83
+ })
84
+
85
+ currentKeyframes.forEach((keyframe) => {
86
+ if (keyframe.parsed) return
87
+ keyframe.parsed = true
88
+ this.emit(keyframe.type, keyframe)
89
+ })
90
+ })
91
+
92
+ }
93
+
94
+
95
+
96
+ /**
97
+ * 载入数据
98
+ */
99
+ async load(vreoUnit: VreoUnit): Promise<boolean> {
100
+ this.vreoUnit = vreoUnit
101
+
102
+ await this.pause()
103
+ return await new Promise((resolve, reject) => {
104
+ if (vreoUnit.video.url === this.audioInstance.src) {
105
+ return resolve(true)
106
+ }
107
+
108
+ this.audioInstance.src = vreoUnit.video.url
109
+ const canplaythrough = () => {
110
+ resolve(true)
111
+ this.audioInstance.removeEventListener('canplaythrough', canplaythrough)
112
+ }
113
+ const error = (err: any) => {
114
+ reject(err)
115
+ this.audioInstance.removeEventListener('error', error)
116
+ }
117
+ this.audioInstance.addEventListener('canplaythrough', canplaythrough)
118
+ this.audioInstance.addEventListener('error', error)
119
+ })
120
+ }
121
+
122
+ /**
123
+ * 播放
124
+ */
125
+ async play() {
126
+ closures.playPromise = this.audioInstance.play()
127
+ }
128
+
129
+ /**
130
+ * 暂停
131
+ */
132
+ async pause() {
133
+ if (closures.playPromise) {
134
+ await closures.playPromise
135
+ }
136
+ this.audioInstance.pause()
137
+ }
138
+
139
+ /**
140
+ * 销毁资源
141
+ * @notice 一旦销毁,创建的实例将不可用:需重新创建实例。
142
+ *
143
+ * @deprecated **慎重执行**
144
+ */
145
+ dispose() {
146
+ // 清理事件监听
147
+ this.audioInstance.removeEventListener('play', closures.onPlaying)
148
+ this.audioInstance.removeEventListener('pasue', closures.onPaused)
149
+ this.audioInstance.removeEventListener('ended', closures.onEnded)
150
+ if (this.stopInterval) {
151
+ this.stopInterval()
152
+ }
153
+ }
154
+ }
155
+
156
+ console.log(`
157
+
158
+ ┏━━━┓━━━━━━━━━┏┓━━━━━━━━━━━━━
159
+ ┃┏━┓┃━━━━━━━━━┃┃━━━━━━━━━━━━━
160
+ ┃┗━┛┃┏━━┓┏━━┓━┃┃━┏━━┓┏━━┓┏━━┓
161
+ ┃┏┓┏┛┃┏┓┃┗━┓┃━┃┃━┃━━┫┃┏┓┃┃┏┓┃
162
+ ┃┃┃┗┓┃┃━┫┃┗┛┗┓┃┗┓┣━━┃┃┃━┫┃┃━┫
163
+ ┗┛┗━┛┗━━┛┗━━━┛┗━┛┗━━┛┗━━┛┗━━┛
164
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
165
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
166
+
167
+ `)
@@ -192,7 +192,6 @@ function SpatialScenePanelBg() {
192
192
  if (!ref.current) return
193
193
 
194
194
  const listener = () => {
195
- console.log('listener')
196
195
  ref.current?.setAttribute('class', 'SpatialScenePanel-bg')
197
196
 
198
197
  timeoutRef.current = setTimeout(() => {
@@ -4,7 +4,7 @@ import { Five, Subscribe } from '@realsee/five'
4
4
 
5
5
  import { App } from './App'
6
6
  import { Controller, ControllerContext } from './Controller'
7
- import { VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
7
+ import { CameraMovementData, VreoKeyframeEnum, VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
8
8
  import { reaction } from 'mobx'
9
9
  import { Drawer } from './modules/Drawer'
10
10
  import { PlayerConfigs } from './typings'
@@ -69,7 +69,7 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
69
69
  )
70
70
  }
71
71
 
72
- async load(vreoUnit: VreoUnit, currentTime = 0) {
72
+ async load(vreoUnit: VreoUnit, currentTime = 0, preload = false) {
73
73
  if (!this.controller.visible) {
74
74
  this.controller.setVisible(true)
75
75
  // 延迟 500ms 规避跟 DOM 动画冲突
@@ -86,6 +86,38 @@ export class Player extends Subscribe<VreoKeyframeEvent> {
86
86
  this.controller.vreoUnit = vreoUnit
87
87
  this.controller.videoInstance?.pause()
88
88
 
89
+ // 预载逻辑
90
+ // 是否降低图片分辨率
91
+ if (this.$five.imageOptions.size && this.configs.imageOptions?.size && this.$five.imageOptions.size > this.configs.imageOptions.size) {
92
+ this.$five.imageOptions.size = this.configs.imageOptions.size
93
+ }
94
+
95
+ // 预载数据中的点位
96
+ if (preload || (preload === undefined && this.configs.autoPreload)) {
97
+ const panoIndexMap = vreoUnit.keyframes.filter((vreoKeyframe) => {
98
+ if (vreoKeyframe.type !== VreoKeyframeEnum.CameraMovement) {
99
+ return false
100
+ }
101
+
102
+ const data = vreoKeyframe.data as CameraMovementData
103
+ if (data.panoIndex === undefined) {
104
+ return false
105
+ }
106
+ return true
107
+ }).reduce((accu: Record<number, boolean>, curr) => {
108
+ const panoIndex = curr.data.panoIndex as number
109
+ if (!accu[panoIndex]) {
110
+ accu[panoIndex] = true
111
+ }
112
+ return accu
113
+ }, {})
114
+
115
+ const panoIndexs = Object.keys(panoIndexMap)
116
+ for (let i = 0; i < panoIndexs.length; i++) {
117
+ await this.$five.preloadPano(Number(panoIndexs[i]))
118
+ }
119
+ }
120
+
89
121
  // 新数据载入就绪
90
122
  this.emit('loaded', vreoUnit)
91
123
  if (vreoUnit.video.url) {
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react'
2
2
  import { CameraMovementPlugin } from '../../../../fivePlugins/CameraMovementPlugin'
3
- import { CameraMovementEffect, RotateArgs } from '../../../../fivePlugins/CameraMovementPlugin/typings'
3
+ import { CameraMovementEffect, MoveArgs, RotateArgs } from '../../../../fivePlugins/CameraMovementPlugin/typings'
4
4
  import { CameraMovementData, VreoKeyframe, VreoKeyframeEnum } from '../../../../typings/VreoUnit'
5
5
  import { useController, useFiveInstance } from '../../../hooks'
6
6
 
@@ -18,9 +18,13 @@ export function CameraMovement() {
18
18
  const cameraMovementData = data as CameraMovementData
19
19
  const effect = cameraMovementData.effect
20
20
  if (effect === CameraMovementEffect.Rotate) {
21
- ref.current.rotate(data as RotateArgs, end - start)
21
+ await ref.current.rotate(data as RotateArgs, end - start)
22
+ } else if (effect === CameraMovementEffect.Move) {
23
+ await ref.current.move(data as MoveArgs, end - start)
24
+ } else if (cameraMovementData.panoIndex !== undefined && cameraMovementData.panoIndex !== five.panoIndex) {
25
+ await ref.current.move(data as MoveArgs, end - start)
22
26
  } else {
23
- ref.current.move(data, end - start)
27
+ await ref.current.rotate(data as RotateArgs, end - start)
24
28
  }
25
29
  }
26
30
 
@@ -6,49 +6,52 @@ import { UpdateVRPanoramaData, VreoKeyframe, VreoKeyframeEnum } from '../../../.
6
6
  export function UpdateVRPanorama() {
7
7
  const controller = useController()
8
8
  const five = useFiveInstance()
9
- const rawRef = React.useRef<string[] | null>(null)
10
- const workRef = React.useRef<Work | null>(null)
9
+ const deafultWorkRef = React.useRef<string[] | null>(null)
10
+ const updateWorkRef = React.useRef<Work | null>(null)
11
11
 
12
12
  const restoreCallback = React.useCallback(() => {
13
- if (rawRef.current) {
14
- const work = parseWork(rawRef.current)
13
+
14
+ if (deafultWorkRef.current) {
15
+ const work = parseWork(deafultWorkRef.current)
15
16
  five.load(work)
16
17
  }
17
18
 
18
- workRef.current = null
19
+ updateWorkRef.current = null
19
20
  }, [])
20
21
 
21
22
  const pausedCallback = React.useCallback(() => {
22
- if (rawRef.current) {
23
- const work = parseWork(rawRef.current)
23
+ if (deafultWorkRef.current) {
24
+ const work = parseWork(deafultWorkRef.current)
25
+ Object.assign(window, {$rawWork: work})
24
26
  five.load(work)
25
27
  }
26
28
  }, [])
27
29
 
28
30
  const playingCallback = React.useCallback(() => {
29
- if (!workRef.current) {
31
+ if (!updateWorkRef.current) {
30
32
  return
31
33
  }
32
- five.load(workRef.current)
34
+ five.load(updateWorkRef.current)
33
35
  }, [])
34
36
 
35
37
  React.useEffect(() => {
36
38
  const callback = (keyframe: VreoKeyframe) => {
37
- if (!rawRef.current) {
38
- rawRef.current = five.work.raw.works
39
+ if (!deafultWorkRef.current) {
40
+ deafultWorkRef.current = five.work.raw.works
39
41
  }
40
42
 
41
43
  const data = keyframe.data as UpdateVRPanoramaData
42
44
 
43
45
  // 如果数据中有新 work 数据,则直接载入
44
46
  if (data.work) {
45
- workRef.current = parseWork(data.work)
46
- five.load(workRef.current)
47
+ updateWorkRef.current = parseWork(data.work)
48
+ five.load(updateWorkRef.current)
47
49
  return
48
50
  }
49
51
 
50
52
  const lastRawWork = five.work?.raw.works[0]
51
53
 
54
+
52
55
  // 动态场景:不提供完成的签名数据,需重新整理
53
56
  if (data.dynamic_scene && !data.panorama) {
54
57
  const lastWork = JSON.parse(lastRawWork)
@@ -59,8 +62,10 @@ export function UpdateVRPanorama() {
59
62
  delete data.dynamic_scene
60
63
  }
61
64
 
62
- workRef.current = parseWork([lastRawWork, data])
63
- five.load(workRef.current)
65
+ Object.assign(window, {$work1: JSON.parse(lastRawWork), $work2: data, parseWork: parseWork})
66
+
67
+ updateWorkRef.current = parseWork([lastRawWork, data])
68
+ five.load(updateWorkRef.current)
64
69
  }
65
70
 
66
71
  controller.on(VreoKeyframeEnum.UpdateVRPanorama, callback)
@@ -20,6 +20,8 @@ export interface PlayerConfigs {
20
20
  */
21
21
  customPanelChildren?: ReactNode
22
22
  customKeyframes?: React.FC<CustomVreoKeyframeProps>[]
23
+ imageOptions?: { size: number }
24
+ autoPreload?: boolean
23
25
  }
24
26
 
25
27
  export type VreoSubscribe = Pick<Subscribe<VreoKeyframeEvent>, 'on' | 'once' | 'off'>