@realsee/vreo 0.2.0-alpha.9 → 1.0.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/CHANGELOG.md +30 -0
- package/README.md +16 -5
- package/docs/assets/highlight.css +1 -1
- package/docs/assets/main.js +2 -2
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +28 -2
- package/docs/classes/Player.AudioLike.html +52 -0
- package/docs/classes/Player.Controller.html +13 -13
- package/docs/classes/Player.Player-1.html +11 -11
- package/docs/classes/Player.VideoAgentMesh.html +53 -53
- package/docs/classes/Player.VideoAgentScene.html +1 -1
- package/docs/demo/assets/AppReact.d0ee843a.js +1 -0
- package/docs/demo/assets/default.63925584.js +3984 -0
- package/docs/demo/assets/default.f3f3ca8c.css +1 -0
- package/docs/demo/assets/dynamic.76506c2c.js +1 -0
- package/docs/demo/assets/examples.3d8323db.js +25 -0
- package/docs/demo/assets/examples.dac4a6fe.css +1 -0
- package/docs/demo/assets/index.7e31122c.js +1 -0
- package/docs/demo/assets/index.9331038f.css +1 -0
- package/docs/demo/assets/main.79b11b9d.js +1 -0
- package/docs/demo/assets/react.2ee8565f.css +1 -0
- package/docs/demo/assets/react.c1c07c14.js +25 -0
- package/docs/demo/assets/znRoyv06SZQeqA7m.0057e8ae.js +1 -0
- package/docs/demo/examples.html +17 -0
- package/docs/demo/index-react-dynamic.html +20 -0
- package/docs/demo/index-react.html +20 -0
- package/docs/demo/index.html +19 -0
- package/docs/enums/Player.InfoPanelStyleEnum.html +1 -1
- package/docs/enums/Player.InfoPanelTypeEnum.html +2 -2
- package/docs/enums/Player.PanoEffectEnum.html +2 -2
- package/docs/enums/Player.PanoTagEnum.html +2 -2
- package/docs/enums/Player.PanoTagStyleEnum.html +7 -0
- 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 +13 -6
- package/docs/interfaces/Player.CustomVreoKeyframeProps.html +1 -1
- package/docs/interfaces/Player.PlayerConfigs.html +4 -3
- package/docs/interfaces/Player.Vertex.html +2 -2
- package/docs/interfaces/Player.VideoAgentMeshOptions.html +8 -1
- package/docs/interfaces/Player.VreoKeyframe.html +2 -2
- package/docs/interfaces/Player.VreoUnit.html +2 -2
- package/docs/interfaces/Player.VreoVideo.html +2 -2
- 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.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/fivePlugins.Vector3Position.html +3 -0
- package/docs/interfaces/react.VreoActionCallbacks.html +15 -7
- package/docs/interfaces/react.VreoProviderProps.html +1 -1
- package/docs/modules/Player.html +21 -15
- package/docs/modules/custom.html +1 -1
- package/docs/modules/fivePlugins.html +5 -2
- package/docs/modules/react.html +1 -1
- package/docs/modules.html +1 -1
- package/lib/PlayController/index.js +4 -5
- package/lib/Player/App.js +9 -7
- package/lib/Player/Controller.d.ts +29 -8
- package/lib/Player/Controller.js +193 -27
- package/lib/Player/custom/SpatialScenePanel/index.js +5 -4
- package/lib/Player/hooks.js +2 -2
- package/lib/Player/index.d.ts +5 -3
- package/lib/Player/index.js +97 -53
- package/lib/Player/modules/Drawer/index.js +1 -1
- package/lib/Player/modules/PopUp/index.js +1 -1
- package/lib/Player/modules/ResizeObserver/index.d.ts +2 -0
- package/lib/Player/modules/ResizeObserver/index.js +37 -0
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.d.ts +16 -2
- package/lib/Player/modules/VideoAgent/VideoAgentMesh.js +132 -59
- package/lib/Player/modules/VideoAgent/VideoAgentScene.d.ts +3 -6
- package/lib/Player/modules/VideoAgent/VideoAgentScene.js +31 -36
- package/lib/Player/modules/VideoAgent/index.js +53 -12
- package/lib/Player/modules/Wave/index.d.ts +5 -0
- package/lib/Player/modules/Wave/index.js +51 -0
- package/lib/Player/modules/keyframes/BgMusic/index.js +1 -1
- package/lib/Player/modules/keyframes/CameraMovement/index.js +1 -1
- package/lib/Player/modules/keyframes/InfoPanel/index.js +22 -10
- package/lib/Player/modules/keyframes/ModelVideo/index.js +46 -9
- package/lib/Player/modules/keyframes/PanoEffect/index.js +1 -1
- package/lib/Player/modules/keyframes/PanoEffect/lineAnime.js +1 -1
- package/lib/Player/modules/keyframes/PanoTag/index.d.ts +1 -2
- package/lib/Player/modules/keyframes/PanoTag/index.js +79 -119
- package/lib/Player/modules/keyframes/PanoTextLabel/index.d.ts +3 -0
- package/lib/Player/modules/keyframes/PanoTextLabel/index.js +96 -44
- package/lib/Player/modules/keyframes/Prompter/index.js +10 -23
- package/lib/Player/modules/keyframes/UpdateVRPanorama/index.js +10 -6
- package/lib/Player/modules/keyframes/VideoEffect/index.js +1 -1
- package/lib/Player/typings.d.ts +12 -1
- 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/fivePlugins/CameraMovementPlugin/index.js +13 -12
- package/lib/fivePlugins/ModelTVVideoPlugin/index.js +1 -1
- package/lib/react/index.d.ts +8 -4
- package/lib/react/index.js +3 -3
- package/lib/shared-utils/AduioLike.d.ts +37 -0
- package/lib/shared-utils/AduioLike.js +166 -0
- package/lib/shared-utils/addResizeListener.d.ts +4 -0
- package/lib/shared-utils/addResizeListener.js +51 -0
- package/lib/shared-utils/animationFrame/BetterTween.js +7 -3
- package/lib/shared-utils/animationFrame/tween.js +1 -1
- package/lib/shared-utils/createTransMatrix.d.ts +1 -0
- package/lib/shared-utils/createTransMatrix.js +43 -0
- package/lib/shared-utils/getFileExpandedName.d.ts +1 -0
- package/lib/shared-utils/getFileExpandedName.js +13 -0
- package/lib/shared-utils/getMediaInfo.d.ts +9 -0
- package/lib/shared-utils/getMediaInfo.js +75 -0
- package/lib/shared-utils/setElementDataset.d.ts +1 -0
- package/lib/shared-utils/setElementDataset.js +24 -0
- package/lib/typings/VreoUnit.d.ts +37 -2
- package/lib/typings/VreoUnit.js +13 -1
- package/package.json +10 -10
- package/resources/PlayController/index.ts +0 -13
- package/resources/Player/App.tsx +5 -4
- package/resources/Player/Controller.ts +277 -146
- package/resources/Player/custom/SpatialScenePanel/index.tsx +5 -5
- package/resources/Player/hooks.ts +3 -5
- package/resources/Player/index.tsx +189 -141
- package/resources/Player/modules/ResizeObserver/index.tsx +23 -0
- package/resources/Player/modules/VideoAgent/VideoAgentMesh.ts +87 -31
- package/resources/Player/modules/VideoAgent/VideoAgentScene.ts +27 -24
- package/resources/Player/modules/VideoAgent/index.tsx +28 -12
- package/resources/Player/modules/Wave/index.tsx +18 -0
- package/resources/Player/modules/keyframes/InfoPanel/index.tsx +26 -11
- package/resources/Player/modules/keyframes/ModelVideo/index.tsx +36 -3
- package/resources/Player/modules/keyframes/PanoTag/index.tsx +53 -97
- package/resources/Player/modules/keyframes/PanoTextLabel/index.tsx +86 -34
- package/resources/Player/modules/keyframes/Prompter/index.tsx +6 -16
- package/resources/Player/modules/keyframes/UpdateVRPanorama/index.tsx +6 -2
- package/resources/Player/typings.ts +15 -1
- 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/fivePlugins/CameraMovementPlugin/index.ts +19 -12
- package/resources/react/index.tsx +7 -3
- package/resources/shared-utils/AduioLike.ts +109 -0
- package/resources/shared-utils/addResizeListener.ts +46 -0
- package/resources/shared-utils/createTransMatrix.ts +12 -0
- package/resources/shared-utils/getFileExpandedName.ts +6 -0
- package/resources/shared-utils/getMediaInfo.ts +52 -0
- package/resources/shared-utils/setElementDataset.ts +18 -0
- package/resources/typings/VreoUnit.ts +41 -3
- package/stylesheets/custom/SpatialScenePanel.css +2 -1
- package/stylesheets/default.css +348 -84
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
1
|
import * as ReactDOM from 'react-dom'
|
|
3
2
|
import { Five, Subscribe } from '@realsee/five'
|
|
4
3
|
|
|
@@ -7,160 +6,209 @@ import { Controller, ControllerContext } from './Controller'
|
|
|
7
6
|
import { CameraMovementData, VreoKeyframeEnum, VreoKeyframeEvent, VreoUnit } from '../typings/VreoUnit'
|
|
8
7
|
import { reaction } from 'mobx'
|
|
9
8
|
import { Drawer } from './modules/Drawer'
|
|
10
|
-
import { PlayerConfigs } from './typings'
|
|
9
|
+
import { Appearance, PlayerConfigs, WaveAppearance } from './typings'
|
|
11
10
|
import { PopUp } from './modules/PopUp'
|
|
12
11
|
|
|
13
12
|
export class Player extends Subscribe<VreoKeyframeEvent> {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(five: Five, configs: Partial<PlayerConfigs> = {}) {
|
|
19
|
-
super()
|
|
20
|
-
this.controller = new Controller()
|
|
21
|
-
this.$five = this.controller.$five = five
|
|
22
|
-
|
|
23
|
-
if (!configs.containter) {
|
|
24
|
-
const containter = document.querySelector('#vreo-app') || document.createElement('div')
|
|
25
|
-
ReactDOM.unmountComponentAtNode(containter)
|
|
26
|
-
containter.setAttribute('id', 'vreo-app')
|
|
27
|
-
configs.containter = containter
|
|
28
|
-
document.body.append(containter)
|
|
29
|
-
}
|
|
13
|
+
$five: Five
|
|
14
|
+
private controller: Controller
|
|
15
|
+
configs: Readonly<PlayerConfigs>
|
|
30
16
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
keyframeMap: {},
|
|
35
|
-
},
|
|
36
|
-
configs
|
|
37
|
-
)
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
this.controller.configs = this.configs
|
|
41
|
-
|
|
42
|
-
ReactDOM.render(
|
|
43
|
-
<ControllerContext.Provider value={this.controller}>
|
|
44
|
-
<App></App>
|
|
45
|
-
<Drawer />
|
|
46
|
-
<PopUp />
|
|
47
|
-
{this.configs.customKeyframes &&
|
|
48
|
-
this.configs.customKeyframes.map((CustomCmpt, key) => (
|
|
49
|
-
<CustomCmpt
|
|
50
|
-
key={key}
|
|
51
|
-
subscribe={{
|
|
52
|
-
on: (name, callback) => this.on(name, callback),
|
|
53
|
-
once: (name, callback) => this.once(name, callback),
|
|
54
|
-
off: (name, callback) => this.off(name, callback),
|
|
55
|
-
}}
|
|
56
|
-
five={five}
|
|
57
|
-
/>
|
|
58
|
-
))}
|
|
59
|
-
</ControllerContext.Provider>,
|
|
60
|
-
configs.containter
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
// 监听播放情况:抛出触发时机
|
|
64
|
-
reaction(
|
|
65
|
-
() => this.controller.playing,
|
|
66
|
-
(playing) => {
|
|
67
|
-
this.emit(playing ? 'playing' : 'paused')
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async load(vreoUnit: VreoUnit, currentTime = 0, preload = false) {
|
|
73
|
-
if (!this.controller.visible) {
|
|
74
|
-
this.controller.setVisible(true)
|
|
75
|
-
// 延迟 500ms 规避跟 DOM 动画冲突
|
|
76
|
-
await new Promise((resolve) => {
|
|
77
|
-
setTimeout(() => resolve(true), 500)
|
|
78
|
-
})
|
|
79
|
-
}
|
|
17
|
+
constructor(five: Five, configs: Partial<PlayerConfigs> = {}) {
|
|
18
|
+
super()
|
|
19
|
+
this.$five = five
|
|
80
20
|
|
|
81
|
-
if (this.controller.stopInterval) {
|
|
82
|
-
this.controller.stopInterval()
|
|
83
|
-
this.controller.stopInterval = undefined
|
|
84
|
-
}
|
|
85
21
|
|
|
86
|
-
|
|
87
|
-
|
|
22
|
+
if (!configs.container) {
|
|
23
|
+
configs.container = configs.containter
|
|
24
|
+
}
|
|
25
|
+
if (!configs.container) {
|
|
26
|
+
const container = document.getElementById('vreo-app') || document.createElement('div')
|
|
27
|
+
ReactDOM.unmountComponentAtNode(container)
|
|
28
|
+
container.setAttribute('id', 'vreo-app')
|
|
29
|
+
configs.container = container
|
|
30
|
+
const fiveCanvasDomParent = five.getElement()?.parentNode
|
|
31
|
+
if (fiveCanvasDomParent) {
|
|
32
|
+
fiveCanvasDomParent.append(container)
|
|
33
|
+
} else {
|
|
34
|
+
document.body.append(container)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
88
37
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
38
|
+
if (!configs.container.classList.contains('vreo-app')) configs.container.classList.add('vreo-app')
|
|
39
|
+
|
|
40
|
+
this.configs = Object.freeze( Object.assign({ keyframeMap: {} }, configs) )
|
|
41
|
+
|
|
42
|
+
this.controller = new Controller({five, container:configs.container, configs: this.configs})
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
ReactDOM.render(
|
|
46
|
+
<ControllerContext.Provider value={this.controller}>
|
|
47
|
+
<App />
|
|
48
|
+
<Drawer />
|
|
49
|
+
<PopUp />
|
|
50
|
+
{this.configs.customKeyframes &&
|
|
51
|
+
this.configs.customKeyframes.map((CustomCmpt, key) => (
|
|
52
|
+
<CustomCmpt
|
|
53
|
+
key={key}
|
|
54
|
+
subscribe={{
|
|
55
|
+
on: (name, callback) => this.on(name, callback),
|
|
56
|
+
once: (name, callback) => this.once(name, callback),
|
|
57
|
+
off: (name, callback) => this.off(name, callback),
|
|
58
|
+
}}
|
|
59
|
+
five={five}
|
|
60
|
+
/>
|
|
61
|
+
))}
|
|
62
|
+
</ControllerContext.Provider>,
|
|
63
|
+
configs.container
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
// 监听播放情况:抛出触发时机
|
|
67
|
+
reaction(
|
|
68
|
+
() => this.controller.ended,
|
|
69
|
+
(ended) => {
|
|
70
|
+
if (ended) {
|
|
71
|
+
this.emit('paused', true)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
reaction(
|
|
77
|
+
() => this.controller.playing,
|
|
78
|
+
(playing) => {
|
|
79
|
+
if (!this.controller.ended) {
|
|
80
|
+
this.emit(playing ? 'playing' : 'paused')
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
)
|
|
93
84
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
85
|
+
|
|
86
|
+
async load(vreoUnit: VreoUnit, currentTime = 0, preload = false, force = false) {
|
|
87
|
+
this.controller.setLoading(true)
|
|
88
|
+
if (force) {
|
|
89
|
+
vreoUnit = JSON.parse(JSON.stringify(vreoUnit))
|
|
90
|
+
}
|
|
91
|
+
if (!this.controller.visible) {
|
|
92
|
+
this.controller.setVisible(true)
|
|
93
|
+
// 延迟 500ms 规避跟 DOM 动画冲突
|
|
94
|
+
await new Promise((resolve) => {
|
|
95
|
+
setTimeout(() => resolve(true), 500)
|
|
96
|
+
})
|
|
100
97
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
|
|
99
|
+
if (this.controller.stopInterval) {
|
|
100
|
+
this.controller.stopInterval()
|
|
101
|
+
this.controller.stopInterval = undefined
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.controller.vreoUnit = vreoUnit
|
|
105
|
+
this.controller.mediaInstance?.pause()
|
|
106
|
+
|
|
107
|
+
// 预载逻辑
|
|
108
|
+
// 是否降低图片分辨率
|
|
109
|
+
if (
|
|
110
|
+
this.$five.imageOptions.size &&
|
|
111
|
+
this.configs.imageOptions?.size &&
|
|
112
|
+
this.$five.imageOptions.size > this.configs.imageOptions.size
|
|
113
|
+
) {
|
|
114
|
+
this.$five.imageOptions.size = this.configs.imageOptions.size
|
|
105
115
|
}
|
|
116
|
+
|
|
117
|
+
// 预载数据中的点位
|
|
118
|
+
if (preload || (preload === undefined && this.configs.autoPreload)) {
|
|
119
|
+
const panoIndexMap = vreoUnit.keyframes
|
|
120
|
+
.filter((vreoKeyframe) => {
|
|
121
|
+
if (vreoKeyframe.type !== VreoKeyframeEnum.CameraMovement) {
|
|
122
|
+
return false
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const data = vreoKeyframe.data as CameraMovementData
|
|
126
|
+
if (data.panoIndex === undefined) {
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
129
|
+
return true
|
|
130
|
+
})
|
|
131
|
+
.reduce((accu: Record<number, boolean>, curr) => {
|
|
132
|
+
const panoIndex = curr.data.panoIndex as number
|
|
133
|
+
if (!accu[panoIndex]) {
|
|
134
|
+
accu[panoIndex] = true
|
|
135
|
+
}
|
|
136
|
+
return accu
|
|
137
|
+
}, {})
|
|
138
|
+
|
|
139
|
+
const panoIndexes = Object.keys(panoIndexMap)
|
|
140
|
+
for (let i = 0; i < panoIndexes.length; i++) {
|
|
141
|
+
await this.$five.preloadPano(Number(panoIndexes[i]))
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 新数据载入就绪
|
|
146
|
+
this.emit('loaded', vreoUnit)
|
|
147
|
+
this.controller.emit('loaded', vreoUnit)
|
|
148
|
+
|
|
149
|
+
if (this.controller.videoAgentScene?.videoAgentMesh.mediaInstance) {
|
|
150
|
+
this.controller.videoAgentScene.videoAgentMesh.mediaInstance.currentTime = currentTime / 1000
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.controller.setAvatar(vreoUnit.video.avatar)
|
|
154
|
+
|
|
155
|
+
await this.controller.videoAgentScene?.videoAgentMesh.play(
|
|
156
|
+
vreoUnit.video.url,
|
|
157
|
+
currentTime / 1000,
|
|
158
|
+
vreoUnit.video.duration
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
this.controller.setEnded(false)
|
|
162
|
+
this.play()
|
|
163
|
+
|
|
164
|
+
this.controller.run((type, keyframe) => this.emit(type, keyframe))
|
|
165
|
+
this.controller.setLoading(false)
|
|
106
166
|
return true
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
get paused() {
|
|
170
|
+
return !this.controller.playing
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
play(currentTime?: number) {
|
|
174
|
+
if (this.controller.playing) return true
|
|
175
|
+
if (currentTime && this.controller.mediaInstance) {
|
|
176
|
+
this.controller.mediaInstance.currentTime = currentTime / 1000
|
|
111
177
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
for (let i = 0; i < panoIndexs.length; i++) {
|
|
117
|
-
await this.$five.preloadPano(Number(panoIndexs[i]))
|
|
118
|
-
}
|
|
178
|
+
Object.assign(window, { $vreoController: this.controller })
|
|
179
|
+
|
|
180
|
+
this.controller.setPlaying(true)
|
|
181
|
+
return true
|
|
119
182
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (vreoUnit.video.url) {
|
|
124
|
-
if (this.controller.videoAgentScene?.videoAgentMesh.videoInstance) {
|
|
125
|
-
this.controller.videoAgentScene.videoAgentMesh.videoInstance.currentTime = currentTime / 1000
|
|
126
|
-
}
|
|
127
|
-
await this.controller.videoAgentScene?.videoAgentMesh.play(vreoUnit.video.url)
|
|
128
|
-
this.play()
|
|
183
|
+
|
|
184
|
+
setAppearance(appearance: Appearance) {
|
|
185
|
+
this.controller.setAppearance(appearance)
|
|
129
186
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
dispose() {
|
|
157
|
-
this.pause()
|
|
158
|
-
this.controller.dispose()
|
|
159
|
-
|
|
160
|
-
if (this.configs.containter) {
|
|
161
|
-
ReactDOM.unmountComponentAtNode(this.configs.containter as Element)
|
|
187
|
+
|
|
188
|
+
pause() {
|
|
189
|
+
this.controller.setPlaying(false)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
show() {
|
|
193
|
+
this.controller.setVisible(true)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
hide() {
|
|
197
|
+
this.controller.setVisible(false)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
getCurrentTime() {
|
|
201
|
+
return this.controller.currentTime
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
dispose() {
|
|
205
|
+
this.pause()
|
|
206
|
+
this.controller.dispose()
|
|
207
|
+
|
|
208
|
+
if (this.configs.container) {
|
|
209
|
+
ReactDOM.unmountComponentAtNode(this.configs.container as Element)
|
|
210
|
+
}
|
|
162
211
|
}
|
|
163
|
-
}
|
|
164
212
|
}
|
|
165
213
|
|
|
166
214
|
console.log(`
|
|
@@ -172,6 +220,6 @@ console.log(`
|
|
|
172
220
|
┃┃┃┗┓┃┃━┫┃┗┛┗┓┃┗┓┣━━┃┃┃━┫┃┃━┫
|
|
173
221
|
┗┛┗━┛┗━━┛┗━━━┛┗━┛┗━━┛┗━━┛┗━━┛
|
|
174
222
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
175
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
223
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
176
224
|
|
|
177
225
|
`)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { addResizeListener, hasResizeListener } from '../../../shared-utils/addResizeListener'
|
|
3
|
+
import { useController } from '../../hooks'
|
|
4
|
+
|
|
5
|
+
export function ResizeObserver() {
|
|
6
|
+
const ref = React.useRef<HTMLDivElement>(null)
|
|
7
|
+
const controller = useController()
|
|
8
|
+
|
|
9
|
+
React.useEffect(() => {
|
|
10
|
+
if (!ref.current) return
|
|
11
|
+
const resizeElement = controller.container.parentElement
|
|
12
|
+
if (hasResizeListener(resizeElement)) return
|
|
13
|
+
const dispose = addResizeListener(resizeElement, (width, height) => {
|
|
14
|
+
controller.setContainerSize(width, height)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
return () => {
|
|
18
|
+
dispose()
|
|
19
|
+
}
|
|
20
|
+
}, [])
|
|
21
|
+
|
|
22
|
+
return <div className="resizeObserver-element" ref={ref}></div>
|
|
23
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
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'
|
|
5
|
+
import { getMediaType } from '../../../shared-utils/getMediaInfo'
|
|
4
6
|
|
|
5
7
|
const vertexShader = `
|
|
6
8
|
varying vec2 vUv;
|
|
@@ -63,8 +65,20 @@ const cacheInstance: {
|
|
|
63
65
|
} = {}
|
|
64
66
|
|
|
65
67
|
export interface VideoAgentMeshOptions {
|
|
68
|
+
/**
|
|
69
|
+
* 自定义视频实例。
|
|
70
|
+
*/
|
|
66
71
|
videoInstance?: HTMLVideoElement
|
|
72
|
+
/**
|
|
73
|
+
* 自定义音频实例。
|
|
74
|
+
*/
|
|
67
75
|
audioInstance?: HTMLAudioElement
|
|
76
|
+
/**
|
|
77
|
+
* 是否开启音频预载能力。**仅对`.mp3`有效**。
|
|
78
|
+
*
|
|
79
|
+
* @description 开启预载能力后会通过 `Fetch/XHR` 方式将音频文件下载转成二进制 [`Blob`](https://developer.mozilla.org/zh-CN/docs/Web/API/Blob) 提供给多媒体实例。这样的好处是 **能够保障音视频播放过程中不卡顿**。 但在部分 iOS 系统中会存在兼容问题——播 25s 之后会静音(`muted` 为 `false`,但是没有声音)。
|
|
80
|
+
*/
|
|
81
|
+
preload?: boolean
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
/**
|
|
@@ -73,17 +87,24 @@ export interface VideoAgentMeshOptions {
|
|
|
73
87
|
export class VideoAgentMesh extends THREE.Mesh {
|
|
74
88
|
options: VideoAgentMeshOptions
|
|
75
89
|
videoUrl?: string
|
|
76
|
-
freeze: boolean
|
|
90
|
+
freeze: boolean
|
|
77
91
|
paused: boolean
|
|
78
92
|
audioInstance: HTMLAudioElement
|
|
93
|
+
audioLikeInstance: AudioLike
|
|
79
94
|
$removeEventListener: () => void
|
|
80
95
|
|
|
81
|
-
get
|
|
82
|
-
if (this.videoUrl
|
|
96
|
+
get mediaInstance(): HTMLAudioElement | HTMLVideoElement | AudioLike {
|
|
97
|
+
if (!this.videoUrl) {
|
|
98
|
+
return this.audioLikeInstance
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (getMediaType(this.videoUrl) === 'audio') {
|
|
83
102
|
return this.audioInstance
|
|
84
103
|
}
|
|
104
|
+
|
|
85
105
|
const uniforms = (this.material as THREE.ShaderMaterial).uniforms
|
|
86
106
|
const videoInstance = uniforms.map.value.image as HTMLVideoElement
|
|
107
|
+
|
|
87
108
|
return videoInstance
|
|
88
109
|
}
|
|
89
110
|
|
|
@@ -100,7 +121,9 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
100
121
|
height: number,
|
|
101
122
|
widthSegments: number,
|
|
102
123
|
heightSegments: number,
|
|
103
|
-
options: VideoAgentMeshOptions = {
|
|
124
|
+
options: VideoAgentMeshOptions = {
|
|
125
|
+
preload: true
|
|
126
|
+
},
|
|
104
127
|
) {
|
|
105
128
|
if (!options.videoInstance) {
|
|
106
129
|
if (cacheInstance.videoInstance) {
|
|
@@ -108,6 +131,7 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
108
131
|
} else {
|
|
109
132
|
const videoInstance = document.createElement('video')
|
|
110
133
|
videoInstance.style.opacity = '0'
|
|
134
|
+
videoInstance.style.pointerEvents = 'none'
|
|
111
135
|
videoInstance.style.display = 'none'
|
|
112
136
|
document.body.append(videoInstance)
|
|
113
137
|
options.videoInstance = videoInstance
|
|
@@ -115,7 +139,6 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
115
139
|
videoInstance.playsInline = true
|
|
116
140
|
videoInstance.controls = false
|
|
117
141
|
}
|
|
118
|
-
|
|
119
142
|
}
|
|
120
143
|
|
|
121
144
|
const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
|
|
@@ -143,10 +166,8 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
143
166
|
audioInstance.crossOrigin = ''
|
|
144
167
|
// videoInstance.muted = true
|
|
145
168
|
audioInstance.muted = false
|
|
146
|
-
audioInstance.
|
|
147
|
-
audioInstance.
|
|
148
|
-
audioInstance.setAttribute('autoplay', 'false')
|
|
149
|
-
audioInstance.setAttribute('style', 'display: none;')
|
|
169
|
+
audioInstance.autoplay = false
|
|
170
|
+
audioInstance.style.display = 'none'
|
|
150
171
|
document.body.appendChild(audioInstance)
|
|
151
172
|
this.audioInstance = audioInstance
|
|
152
173
|
cacheInstance.audioInstance = audioInstance
|
|
@@ -155,69 +176,104 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
155
176
|
this.audioInstance = options.audioInstance
|
|
156
177
|
}
|
|
157
178
|
|
|
179
|
+
this.audioLikeInstance = new AudioLike()
|
|
180
|
+
|
|
158
181
|
makeObservable(this, { paused: observable })
|
|
159
182
|
|
|
160
183
|
const updatePaused = (paused: boolean) => runInAction(() => (this.paused = paused))
|
|
161
184
|
const onPause = () => updatePaused(true)
|
|
162
185
|
const onPlay = () => updatePaused(false)
|
|
186
|
+
const onEnded = () => console.log('vreo: video 播放结束')
|
|
163
187
|
|
|
164
|
-
this.
|
|
165
|
-
this.
|
|
188
|
+
this.audioInstance.addEventListener('pause', onPause)
|
|
189
|
+
this.audioInstance.addEventListener('play', onPlay)
|
|
190
|
+
this.options.videoInstance?.addEventListener('pause', onPause)
|
|
191
|
+
this.options.videoInstance?.addEventListener('play', onPlay)
|
|
192
|
+
this.audioLikeInstance.addEventListener('pause', onPause)
|
|
193
|
+
this.audioLikeInstance.addEventListener('play', onPlay)
|
|
194
|
+
this.options.videoInstance?.addEventListener('ended', onEnded)
|
|
166
195
|
|
|
167
196
|
this.$removeEventListener = () => {
|
|
168
|
-
this.
|
|
169
|
-
this.
|
|
197
|
+
this.audioInstance.removeEventListener('pause', onPause)
|
|
198
|
+
this.audioInstance.removeEventListener('play', onPlay)
|
|
199
|
+
this.options.videoInstance?.removeEventListener('pause', onPause)
|
|
200
|
+
this.options.videoInstance?.removeEventListener('play', onPlay)
|
|
201
|
+
this.audioLikeInstance.removeEventListener('pause', onPause)
|
|
202
|
+
this.audioLikeInstance.removeEventListener('play', onPlay)
|
|
203
|
+
this.options.videoInstance?.removeEventListener('ended', onEnded)
|
|
170
204
|
}
|
|
171
205
|
}
|
|
172
206
|
|
|
173
|
-
|
|
174
207
|
private async update(videoUrl: string) {
|
|
208
|
+
|
|
175
209
|
if (this.videoUrl === videoUrl) {
|
|
176
210
|
return
|
|
177
211
|
}
|
|
178
212
|
|
|
179
213
|
this.videoUrl = videoUrl
|
|
214
|
+
|
|
215
|
+
// // 兼容非视频场景
|
|
216
|
+
// if (this.mediaInstance instanceof HTMLAudioElement) {
|
|
217
|
+
// this.mediaInstance.style.display = 'none'
|
|
218
|
+
// } else if (this.mediaInstance instanceof HTMLVideoElement) {
|
|
219
|
+
// this.mediaInstance.style.display = 'block'
|
|
220
|
+
// }
|
|
221
|
+
|
|
180
222
|
this.freeze = true
|
|
181
|
-
await this.
|
|
223
|
+
await this.mediaInstance.pause()
|
|
182
224
|
|
|
183
225
|
const uniforms = (this.material as THREE.ShaderMaterial).uniforms
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
this.
|
|
226
|
+
this.mediaInstance.muted = true
|
|
227
|
+
|
|
228
|
+
this.mediaInstance.src = (this.options.preload || this.options.preload === undefined || getMediaType(this.videoUrl) === 'video') ?
|
|
229
|
+
await URL.createObjectURL((await Preloader.blob(this.videoUrl)) as unknown as Blob) : this.videoUrl
|
|
230
|
+
this.mediaInstance.setAttribute('data-src', this.videoUrl)
|
|
187
231
|
|
|
188
232
|
const onStart = () => {
|
|
189
|
-
if (this.
|
|
233
|
+
if (this.mediaInstance.currentTime === 0) return
|
|
190
234
|
this.freeze = false
|
|
191
|
-
this.
|
|
192
|
-
uniforms.enable.value = this.videoUrl
|
|
193
|
-
this.
|
|
235
|
+
this.mediaInstance.muted = false
|
|
236
|
+
uniforms.enable.value = getMediaType(this.videoUrl) ? 1 : 0
|
|
237
|
+
this.mediaInstance.removeEventListener('timeupdate', onStart, false)
|
|
238
|
+
|
|
194
239
|
}
|
|
195
240
|
|
|
196
|
-
this.
|
|
241
|
+
this.mediaInstance.addEventListener('timeupdate', onStart, false)
|
|
197
242
|
}
|
|
198
243
|
|
|
199
|
-
async play(videoUrl = '') {
|
|
244
|
+
async play(videoUrl = '', currentTime = 0, duration?: number) {
|
|
200
245
|
videoUrl = videoUrl || ''
|
|
246
|
+
|
|
247
|
+
if (duration && !videoUrl) {
|
|
248
|
+
if (this.currentTime) {
|
|
249
|
+
this.mediaInstance.currentTime = currentTime
|
|
250
|
+
}
|
|
251
|
+
(this.mediaInstance as AudioLike).duration = duration
|
|
252
|
+
this.videoUrl = ''
|
|
253
|
+
this.mediaInstance.play()
|
|
254
|
+
return true
|
|
255
|
+
}
|
|
256
|
+
|
|
201
257
|
if (!videoUrl) {
|
|
202
|
-
if (this.videoUrl) await this.
|
|
258
|
+
if (this.videoUrl) await this.mediaInstance.play()
|
|
203
259
|
else console.warn('警告:视频资源未初始化。')
|
|
204
260
|
return true
|
|
205
261
|
}
|
|
206
262
|
|
|
207
263
|
if (videoUrl === this.videoUrl) {
|
|
208
|
-
this.
|
|
209
|
-
await this.
|
|
264
|
+
this.mediaInstance.currentTime = currentTime
|
|
265
|
+
await this.mediaInstance.play()
|
|
210
266
|
return true
|
|
211
267
|
}
|
|
212
268
|
|
|
213
269
|
await this.update(videoUrl)
|
|
214
270
|
|
|
215
|
-
this.
|
|
271
|
+
this.mediaInstance.pause()
|
|
216
272
|
|
|
217
273
|
return await new Promise((resolve) =>
|
|
218
274
|
setTimeout(async () => {
|
|
219
|
-
this.
|
|
220
|
-
await this.
|
|
275
|
+
this.mediaInstance.currentTime = currentTime
|
|
276
|
+
await this.mediaInstance.play()
|
|
221
277
|
resolve(true)
|
|
222
278
|
}, 20),
|
|
223
279
|
)
|
|
@@ -227,7 +283,7 @@ export class VideoAgentMesh extends THREE.Mesh {
|
|
|
227
283
|
* 转成毫秒,保障精准度
|
|
228
284
|
*/
|
|
229
285
|
get currentTime() {
|
|
230
|
-
return this.
|
|
286
|
+
return this.mediaInstance.currentTime * 1000
|
|
231
287
|
}
|
|
232
288
|
|
|
233
289
|
dispose() {
|