diff --git a/example/src/app.js b/example/src/app.js
index 0d36e90..647630d 100644
--- a/example/src/app.js
+++ b/example/src/app.js
@@ -6,6 +6,9 @@ import * as THREE from 'three';
import EmbeddedTextBox from "../../src/display/ResourceBox/EmbeddedResource/EmbeddedTextBox";
import EmbeddedImageBox from "../../src/display/ResourceBox/EmbeddedResource/EmbeddedImageBox";
import EmbeddedVideoBox from "../../src/display/ResourceBox/EmbeddedResource/EmbeddedVideoBox";
+import EventBus from "../../src/event/EventBus";
+import Events from "../../src/event/Events";
+
class App extends React.Component {
state = {
@@ -49,7 +52,7 @@ class App extends React.Component {
this.xrManager.setFovVerticalScope(0, 180);
this.xrManager.enableKeyControl(true);
this.xrManager.enableChangeFov(true);
- this.xrManager.cameraTweenGroup.enableAutoNext(true);
+ this.xrManager.playingCameraTweenGroup.enableAutoNext(true);
// this.onCameraAnimationSet();
}
@@ -70,10 +73,10 @@ class App extends React.Component {
}
]
var cameraTweenGroup = this.xrManager.createCameraTweenGroup(animateList, true);
- //cameraTweenGroup.enableAutoNext(true);
+ //playingCameraTweenGroup.enableAutoNext(true);
this.xrManager.setCameraTweenGroup(cameraTweenGroup);
// this.xrManager.onCameraAnimationEnded = (index) => {
- // cameraTweenGroup.next();
+ // playingCameraTweenGroup.next();
// }
}
@@ -90,24 +93,28 @@ class App extends React.Component {
onAddHotSpot = () => {
this.xrManager.addHotSpot({
- key: `infocard`,
+ key: 'infocard_test',
value: {
- lat: - 90, lon: -10,
+ lat: 90, lon: 0,
res_url: 'https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png'
}
}, {
- key: `infocard`,
- value: {
- id: 'infocard',
- type: 'infocard',
- iframeUrl: "https://gs.ctrip.com/html5/you/place/14.html"
+ type: "event_pop_effect_panel",
+ props: {
+ name: "infocard",
+ props: {
+ data: {
+ type: "infocard",
+ iframeUrl: "https://gs.ctrip.com/html5/you/place/14.html"
+ }
+ }
}
- })
+ });
alert(`添加了一个热点标签`)
}
onRemoveHotSpot = () => {
- this.xrManager.removeHotSpot('infocard')
+ this.xrManager.removeHotSpot('infocard_test')
alert(`移除了一个热点标签`);
}
@@ -327,32 +334,18 @@ class App extends React.Component {
}
onPickDirector = () => {
- let pos = this.xrManager.getCameraLatLon();
- let fov = this.xrManager.getCameraFov();
- let startLat = 90, startLon = 180;
- if (this.autoDisplayList.length !== 0) {
- startLat = this.autoDisplayList[this.autoDisplayList.length - 1].end.lat;
- startLon = this.autoDisplayList[this.autoDisplayList.length - 1].end.lon;
- }
- this.autoDisplayList.push({
- start: { lat: startLat, lon: startLon, fov: 80, distance: 500 },
- end: { lat: pos.lat, lon: pos.lon, fov: fov, distance: 500 },
- duration: 5000, easing: TWEEN.Easing.Sinusoidal.InOut,
- })
+ this.xrManager.pickDirector('name');
}
onStartAutoDisplay = () => {
- var cameraTweenGroup = this.xrManager.createCameraTweenGroup(this.autoDisplayList, true);
- this.xrManager.setCameraTweenGroup(cameraTweenGroup);
- cameraTweenGroup.enableAutoNext(true);
- this.xrManager.startCameraTweenGroup();
+ this.xrManager.createDemonstrateCameraTween()
}
debugFunc = () => {
- let videoBox = this.boxManager.getEmbeddedBox('box3');
- console.log(videoBox.getPosition())
+ console.log(this.xrManager.exportConfig());
}
+
render() {
return (
@@ -408,12 +401,14 @@ class App extends React.Component {
+
+
+
+
-
-
diff --git a/public/mock/view1.json b/public/mock/view1.json
index 79bafec..14e9b5f 100644
--- a/public/mock/view1.json
+++ b/public/mock/view1.json
@@ -24,9 +24,9 @@
]
],
"hot_spot_list": [
- [
- "zhong_shan_she_qu",
- {
+ {
+ "key": "zhong_shan_she_qu",
+ "props": {
"lat": 140,
"lon": -40,
"position": "top",
@@ -36,12 +36,25 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/zhong_shan_she_qu.jpg",
"img_height": 100,
- "img_width": 150
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "image",
+ "props": {
+ "data": {
+ "type": "image",
+ "imageUrl": "https://pic-cloud-bupt.oss-cn-beijing.aliyuncs.com/5c882ee6443a5.jpg",
+ "jumpUrl": "http://www.youmuvideo.com"
+ }
+ }
+ }
+ }
}
- ],
- [
- "zhong_shan_ji_nian_tang",
- {
+ },
+ {
+ "key": "zhong_shan_ji_nian_tang",
+ "props": {
"lat": 310,
"lon": -60,
"animate": true,
@@ -50,12 +63,24 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/zhong_shan_ji_nian_tang.jpg",
"img_height": 100,
- "img_width": 150
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "video",
+ "props": {
+ "data": {
+ "type": "video",
+ "videoUrl": "https://video-cloud-bupt.oss-cn-beijing.aliyuncs.com/hangzhou.mp4"
+ }
+ }
+ }
+ }
}
- ],
- [
- "ling_ze_xu",
- {
+ },
+ {
+ "key": "ling_ze_xu",
+ "props": {
"lat": 305,
"lon": 55,
"animate": true,
@@ -65,12 +90,24 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/lin_ze_xu_chu_sheng_di.jpg",
"img_height": 100,
- "img_width": 150
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "infocard",
+ "props": {
+ "data": {
+ "type": "infocard",
+ "iframeUrl": "https://gs.ctrip.com/html5/you/place/14.html"
+ }
+ }
+ }
+ }
}
- ],
- [
- "ma_qiu_chang",
- {
+ },
+ {
+ "key": "ma_qiu_chang",
+ "props": {
"lat": 320,
"lon": 20,
"animate": true,
@@ -79,12 +116,31 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/tang_dai_ma_qiu_chang_yi_zhi.jpg",
"img_height": 100,
- "img_width": 150
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "alpha_video",
+ "props": {
+ "data": {
+ "id": "video",
+ "type": "alpha_video",
+ "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
+ "width": "60vw",
+ "height": "60vw",
+ "enableClose": true,
+ "margin": "auto auto",
+ "videoMuted": false,
+ "enableMask": true
+ }
+ }
+ }
+ }
}
- ],
- [
- "ren_shou_tang",
- {
+ },
+ {
+ "key": "ren_shou_tang",
+ "props": {
"lat": 360,
"lon": 20,
"animate": true,
@@ -93,12 +149,31 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.jpg",
"img_height": 100,
- "img_width": 150
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "alpha_video",
+ "props": {
+ "data": {
+ "id": "video",
+ "type": "alpha_video",
+ "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
+ "width": "60vw",
+ "height": "60vw",
+ "enableClose": true,
+ "margin": "auto auto",
+ "videoMuted": false,
+ "enableMask": true
+ }
+ }
+ }
+ }
}
- ],
- [
- "ou_ye_chi",
- {
+ },
+ {
+ "key": "ou_ye_chi",
+ "props": {
"lat": 410,
"lon": 40,
"animate": true,
@@ -108,75 +183,28 @@
"res_url": "https://live360.oss-cn-beijing.aliyuncs.com/xr/icons/hotspot_video.png",
"img_url": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ou_ye_chi_yi_zhi.jpg",
"img_height": 100,
- "img_width": 150
- }
- ]
- ],
- "event_list": [
- [
- "zhong_shan_she_qu",
- {
- "type": "image",
- "imageUrl": "https://pic-cloud-bupt.oss-cn-beijing.aliyuncs.com/5c882ee6443a5.jpg",
- "jumpUrl": "http://www.youmuvideo.com"
- }
- ],
- [
- "zhong_shan_ji_nian_tang",
- {
- "type": "video",
- "videoUrl": "https://video-cloud-bupt.oss-cn-beijing.aliyuncs.com/hangzhou.mp4"
- }
- ],
- [
- "ling_ze_xu",
- {
- "type": "infocard",
- "iframeUrl": "https://gs.ctrip.com/html5/you/place/14.html"
+ "img_width": 150,
+ "event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "alpha_video",
+ "props": {
+ "data": {
+ "id": "video",
+ "type": "alpha_video",
+ "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
+ "width": "60vw",
+ "height": "60vw",
+ "enableClose": true,
+ "margin": "auto auto",
+ "videoMuted": false,
+ "enableMask": true
+ }
+ }
+ }
+ }
}
- ],
- [
- "ma_qiu_chang",
- {
- "id": "video",
- "type": "alpha_video",
- "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
- "width": "60vw",
- "height": "60vw",
- "enableClose": true,
- "margin": "auto auto",
- "videoMuted": false,
- "enableMask": true
- }
- ],
- [
- "ou_ye_chi",
- {
- "id": "video",
- "type": "alpha_video",
- "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
- "width": "60vw",
- "height": "60vw",
- "enableClose": true,
- "margin": "auto auto",
- "videoMuted": false,
- "enableMask": true
- }
- ],
- [
- "ren_shou_tang",
- {
- "id": "video",
- "type": "alpha_video",
- "videoUrl": "https://youmucloud.oss-cn-beijing.aliyuncs.com/xr/fuzhou/ren_shou_tang.mp4",
- "width": "60vw",
- "height": "60vw",
- "enableClose": true,
- "margin": "auto auto",
- "videoMuted": false,
- "enableMask": true
- }
- ]
+ }
],
"particle_effect": {
"url": "https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/sprites/snowflake1.png",
@@ -189,26 +217,41 @@
{
"key": "zhong_shan_ji_nian_tang",
"start": {
+ "name": "zhong_shan_ji_nian_tang",
"lat": 90,
"lon": -15,
"fov": 90
},
"end": {
+ "name": "ling_ze_xu",
"lat": 69,
"lon": 110,
"fov": 58
},
"duration": 5000,
- "easing": "InOut"
+ "easing": "InOut",
+ "complete_event": {
+ "type": "event_pop_effect_panel",
+ "props": {
+ "name": "image",
+ "props": {"data":{
+ "type": "image",
+ "imageUrl": "https://pic-cloud-bupt.oss-cn-beijing.aliyuncs.com/5c882ee6443a5.jpg",
+ "jumpUrl": "http://www.youmuvideo.com"
+ }}
+ }
+ }
},
{
"key": "ling_ze_xu",
"start": {
+ "name": "ling_ze_xu",
"lat": 69,
"lon": 110,
"fov": 58
},
"end": {
+ "name": "ma_qiu_chang",
"lat": 105,
"lon": 110,
"fov": 58
@@ -219,11 +262,13 @@
{
"key": "ma_qiu_chang",
"start": {
+ "name": "ma_qiu_chang",
"lat": 105,
"lon": 110,
"fov": 58
},
"end": {
+ "name": "ren_shou_tang",
"lat": 100,
"lon": 137,
"fov": 38
@@ -234,11 +279,13 @@
{
"key": "ren_shou_tang",
"start": {
+ "name": "ren_shou_tang",
"lat": 100,
"lon": 137,
"fov": 38
},
"end": {
+ "name": "ou_ye_chi",
"lat": 100,
"lon": 180,
"fov": 70
@@ -249,11 +296,13 @@
{
"key": "ou_ye_chi",
"start": {
+ "name": "ou_ye_chi",
"lat": 100,
"lon": 180,
"fov": 70
},
"end": {
+ "name": "zhong_shan_she_qu",
"lat": 91.5,
"lon": 206,
"fov": 80
@@ -264,11 +313,13 @@
{
"key": "zhong_shan_she_qu",
"start": {
+ "name": "zhong_shan_she_qu",
"lat": 91.5,
"lon": 206,
"fov": 80
},
"end": {
+ "name": "end",
"lat": 90,
"lon": -15,
"fov": 90
diff --git a/src/Player.js b/src/Player.js
index 4804a68..c214edc 100644
--- a/src/Player.js
+++ b/src/Player.js
@@ -91,6 +91,10 @@ class XRPlayer extends Component {
let result = this.props.onEventHandler(props.type, props);
if (result) return;
}, this);
+ //注册弹窗事件
+ EventBus.on(Events.EVENT_POP_EFFECT_PANEL, (props) => {
+ this.eventHandler(props.name, props.props, props.callback);
+ }, this);
window.addEventListener('resize', this.onWindowResize, false);
}
diff --git a/src/controls/CameraTween.js b/src/controls/CameraTween.js
index fafe7a7..dfaad2e 100644
--- a/src/controls/CameraTween.js
+++ b/src/controls/CameraTween.js
@@ -1,5 +1,7 @@
import * as THREE from 'three';
import TWEEN from '@tweenjs/tween.js';
+import EventBus from "../event/EventBus";
+import Events from "../event/Events";
class CameraTween {
constructor(tweenParams, camera, cameraDistance, cameraControl) {
@@ -20,9 +22,6 @@ class CameraTween {
this.reset = cameraControl.initSphericalData; //动画结束后视角停在结束的位置,不会回到之前的位置
this.started = false; //在start之后stop之前调用start会导致不会调用onStop,无法使用相机控制
- this.startTime = 0;
- this.endTime = 0;
-
this.posType = 0; // 0 表示都不用, 1 采用xyz, 2 采用经纬度
this.fovChange = false; //是否涉及fov的改变
this.disChange = false; //是否涉及distance的改变
@@ -30,6 +29,9 @@ class CameraTween {
this.onCameraAnimationEnded = null; // 动画结束后回调
this.onCameraAnimationStop = null;
this.onCameraAnimationStart = null;
+
+ this.completeEventParams = null;
+
this.init(tweenParams);
}
@@ -38,6 +40,8 @@ class CameraTween {
this.easing = params.easing;
this.pos0 = {};
this.pos1 = {};
+ this.completeEventParams = {};
+ Object.assign(this.completeEventParams, params.complete_event)
Object.assign(this.pos0, params.start);
Object.assign(this.pos1, params.end);
this.tween = new TWEEN.Tween(this.pos0).to(this.pos1, params.duration);
@@ -52,6 +56,9 @@ class CameraTween {
this.onCameraAnimationEnded(this.key);
this.reset();
this.started = false;
+ if (this.completeEventParams.type && this.completeEventParams.props) {
+ EventBus.trigger(this.completeEventParams.type, this.completeEventParams.props);
+ }
});
this.tween.onStop(() => {
this.onCameraAnimationStop &&
@@ -104,6 +111,10 @@ class CameraTween {
});
}
+ setCompleteEvent = (params) => {
+ this.completeEventParams = params;
+ }
+
setFocus = (focus) => {
this.focus.x = focus.x;
this.focus.y = focus.y;
diff --git a/src/display/SpriteShapeHelper.js b/src/display/SpriteShapeHelper.js
index a279d6a..28d412b 100644
--- a/src/display/SpriteShapeHelper.js
+++ b/src/display/SpriteShapeHelper.js
@@ -4,6 +4,7 @@
import * as THREE from 'three';
import { Radius } from '../const/PanoConst';
import TWEEN from '@tweenjs/tween.js';
+import EventBus from "../event/EventBus";
class SpriteShapeHelper {
@@ -16,11 +17,36 @@ class SpriteShapeHelper {
this.hotSpotMap = null; // 热点标签数据
this.hotSpotMeshMap = null; // 热点标签Mesh Map,便于动态缩减
this.pointGroup = null; // 场景中的热点组合
+ this.eventMap = null; // 热点事件
this.objectClickHandler = null;
this.tagClickHandler = null;
this.isTipVisible = true;
this.hotSpotClickable = true;
+
+ this.initHandler();
+ }
+
+ initHandler = () => {
+ this.objectClickHandler = (intersects) => {
+ const key = intersects[0].object.name;
+ if (this.hotSpotMap && this.hotSpotMap.has(key)) {
+ let hotSpot = this.hotSpotMap.get(key);
+ let event = hotSpot.event;
+ if (event) {
+ EventBus.trigger(event.type, event.props);
+ }
+ }
+ };
+ this.tagClickHandler = (key) => {
+ if (this.hotSpotMap && this.hotSpotMap.has(key)) {
+ let hotSpot = this.hotSpotMap.get(key);
+ let event = hotSpot.event;
+ if (event) {
+ EventBus.trigger(event.type, event.props);
+ }
+ }
+ }
}
setIsTipVisible = (enable) => {
@@ -63,19 +89,40 @@ class SpriteShapeHelper {
setHotSpotList = (hot_spot_list) => {
this.resetHotSpotGroup();
- this.hotSpotMap = new Map(hot_spot_list);
+ this.hotSpotMap = new Map();
+ // this.eventMap = new Map();
+ hot_spot_list.forEach((spot) => {
+ this.hotSpotMap.set(spot.key, spot.props);
+ });
this.hotSpotMap.forEach((value, key) => {
this.createPoint(key, value)
});
}
- addHotSpot = (hot_spot) => {
+ // setEventList = (eventList) => {
+ // this.eventMap = new Map(eventList);
+ // console.log('event_map')
+ // console.log(this.eventMap)
+ // }
+
+ addHotSpot = (hot_spot, event) => {
if (!this.pointGroup) {
this.resetHotSpotGroup();
}
- this.createPoint(hot_spot.key, hot_spot.value)
+ this.hotSpotMap || (this.hotSpotMap = new Map());
+ if (!!!hot_spot.value) return false;
+ hot_spot.value.event = event;
+ this.hotSpotMap.set(hot_spot.key, hot_spot.value);
+ this.createPoint(hot_spot.key, hot_spot.value);
+ return true;
}
+ // addEvent = (event) => {
+ // if (event && !this.eventMap.has(event.key)) {
+ // this.eventMap.set(event.key, event.value);
+ // }
+ // }
+
/**
* 清空场景中的所有热点标签
*/
@@ -89,6 +136,7 @@ class SpriteShapeHelper {
this.container.removeChild(div);
}
});
+ this.hotSpotMap = new Map();
}
removeHotSpot = (hot_spot_key) => {
@@ -96,9 +144,25 @@ class SpriteShapeHelper {
if (mesh) {
this.pointGroup.remove(mesh);
}
+ this.hotSpotMap.delete(hot_spot_key);
+ this.hotSpotMap && (this.hotSpotMap.delete(hot_spot_key));
+ }
+
+ /**
+ * @function
+ * @name SpriteShapeHelper#exportConfig
+ * @description 导出热点标签配置信息
+ */
+ exportConfig = () => {
+ if (!!!this.hotSpotMap) return [];
+ let config = [];
+ this.hotSpotMap.forEach((value, key) => {
+ config.push({key: key, props: value});
+ });
+ return config;
}
- contertSph2Rect = (lat, lon) => {
+ convertSph2Rect = (lat, lon) => {
let r = Radius;
const phi = THREE.Math.degToRad(lat);
const theta = THREE.Math.degToRad(lon);
@@ -113,7 +177,7 @@ class SpriteShapeHelper {
let { lat, lon, res_url, opacity = 1, scale = 16,
animate = false, title = null, img_url = null,
img_height = 100, img_width = 100, title_width } = value;
- let position = this.contertSph2Rect(lat, lon);
+ let position = this.convertSph2Rect(lat, lon);
let meshGroup = new THREE.Group();
meshGroup.name = key;
meshGroup.position.set(...position);
@@ -309,12 +373,12 @@ class SpriteShapeHelper {
const container = document.getElementById('xr-container')
container.addEventListener('click', (event) => {
event.preventDefault();
- console.log('检测热点点击');
+ // console.log('检测热点点击');
var intersects = this.getIntersects(event);
//如果只需要将第一个触发事件,那就取数组的第一个模型
if (intersects.length > 0) {
if (this.objectClickHandler) {
- console.log('intersects', intersects);
+ // console.log('intersects', intersects);
this.objectClickHandler(intersects);
}
}
diff --git a/src/event/EventBus.js b/src/event/EventBus.js
index cda786e..4883cdc 100644
--- a/src/event/EventBus.js
+++ b/src/event/EventBus.js
@@ -96,7 +96,7 @@ class EventBus {
if (payload.hasOwnProperty('type')) throw new Error('\'type\' is a reserved word for event dispatching');
- payload.type = type;
+ // payload.type = type;
this.handlers[type] = this.handlers[type].filter((item) => item);
this.handlers[type].forEach(handler => handler && handler.callback.call(handler.scope, payload));
diff --git a/src/event/Events.js b/src/event/Events.js
index 019e33f..59c9626 100644
--- a/src/event/Events.js
+++ b/src/event/Events.js
@@ -3,7 +3,8 @@
*/
const EVENT_SENCE_RES_READY = 'event_sence_res_ready'; //全景背景资源准备完成
-
+const EVENT_POP_EFFECT_PANEL = 'event_pop_effect_panel'; //弹出弹窗
export default {
- EVENT_SENCE_RES_READY
+ EVENT_SENCE_RES_READY,
+ EVENT_POP_EFFECT_PANEL
};
diff --git a/src/manager/XRPlayerManager.js b/src/manager/XRPlayerManager.js
index 3500b3c..adefee4 100644
--- a/src/manager/XRPlayerManager.js
+++ b/src/manager/XRPlayerManager.js
@@ -39,6 +39,7 @@ class XRPlayerManager {
this.handler = handler;
this.scene = null;
+ this.radius = null;
this.sceneMesh = null;
this.camera = null;
this.renderer = null;
@@ -46,7 +47,6 @@ class XRPlayerManager {
this.sceneContainer = null; // 全景背景挂载节点
this.sceneTextureHelper = null; //全景场景纹理加载控制器
-
this.innerViewControls = null;
this.spriteShapeHelper = null;
this.spriteParticleHelper = null; // 粒子展示
@@ -68,7 +68,9 @@ class XRPlayerManager {
num: 0,
paused: false
};
- this.cameraTweenGroup = null;
+ this.playingCameraTweenGroup = null;
+ this.creatingDirectors = [];
+ this.directorDurations = [];
this.onCameraAnimationEnded = null;
@@ -111,6 +113,7 @@ class XRPlayerManager {
axes_helper_display: isAxesHelperDisplay,
} = this.props;
const { panoramic_type = '360', radius = 500, height = 1000 } = textureResource;
+ this.radius = radius;
this.sceneContainer = document.getElementById('video');
let geometry;
if (panoramic_type === '180') {
@@ -222,9 +225,8 @@ class XRPlayerManager {
if (config.hasOwnProperty('muted')) {
this.setGlobalMuted(config.muted);
}
- if (config.hasOwnProperty('hot_spot_list')
- && config.hasOwnProperty('event_list')) {
- this.setHotSpots(config.hot_spot_list, config.event_list);
+ if (config.hasOwnProperty('hot_spot_list')) {
+ this.setHotSpots(config.hot_spot_list);
}
if (config.hasOwnProperty('particle_effect')) {
this.setParticleEffectRes(config.particle_effect);
@@ -255,8 +257,9 @@ class XRPlayerManager {
// TODO 需要从状态中读取,即需要解决一致性问题
config.volume = this.senceConfig.volume;
config.muted = this.senceConfig.muted;
- config.hot_spot_list = this.senceConfig.hot_spot_list;
- config.event_list = this.senceConfig.event_list;
+
+ config.hot_spot_list = this.spriteShapeHelper.exportConfig();
+
config.model_list = this.senceConfig.model_list;
config.particle_effect = this.senceConfig.particle_effect;
config.auto_guide_list = this.senceConfig.auto_guide_list;
@@ -347,36 +350,20 @@ class XRPlayerManager {
/****************************热点标签相关控制接口************************* */
resetHotSpotsData = () => {
if (!this.spriteShapeHelper) {
- this.spriteEventList = new Map();
this.spriteShapeHelper = new SpriteShapeHelper(this.scene,
this.camera, this.renderer, this.mount);
} else {
- this.spriteEventList.clear();
+ this.spriteShapeHelper.resetHotSpotGroup();
}
}
- setHotSpots = (hot_spot_list, event_list) => {
+ setHotSpots = (hot_spot_list) => {
this.resetHotSpotsData();
- this.spriteEventList = new Map(event_list);
this.spriteShapeHelper.setHotSpotList(hot_spot_list);
- this.spriteShapeHelper.objectClickHandler = (intersects) => {
- const key = intersects[0].object.name;
- this.emitEvent(key, () => {
- this.closeEffectContainer();
- })
- }
- this.spriteShapeHelper.tagClickHandler = (key) => {
- this.emitEvent(key, () => {
- this.closeEffectContainer();
- })
- }
}
addHotSpot = (hot_spot, event) => {
- this.spriteShapeHelper.addHotSpot(hot_spot);
- if (event != null && !this.spriteEventList.has(event.key)) {
- this.spriteEventList.set(event.key, event.value);
- }
+ return this.spriteShapeHelper.addHotSpot(hot_spot, event);
}
removeHotSpot = (hot_spot_key) => {
@@ -463,9 +450,9 @@ class XRPlayerManager {
/**
* @function
* @name XRPlayerManager#moveCameraTo
- * @param {*} descPos 相机目标位置,采用lat,lon表示
+ * @param {*} endPos 相机目标位置,采用lat,lon表示
* @param {function} onStart 移动开始事件回调
- * @param {functon} onEnd 移动结束事件回调
+ * @param {function} onEnd 移动结束事件回调
* @param {number} duration 相机移动动画的持续时长
* @param {number} delay 相机动画延迟启动时长
*/
@@ -622,7 +609,7 @@ class XRPlayerManager {
simpleCreateTextBox = (boxId) => { //在相机聚焦位置创建一个初始文本框
let textBox = new EmbeddedTextBox(boxId);
textBox.setText('简易文本框');
- let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
+ let position = this.getCameraPosition().clone().normalize().multiplyScalar(-this.radius);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
@@ -635,7 +622,7 @@ class XRPlayerManager {
simpleCreateImageBox = (boxId) => { //在相机聚焦位置创建一个初始图片框
let textBox = new EmbeddedImageBox(boxId);
- let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
+ let position = this.getCameraPosition().clone().normalize().multiplyScalar(-this.radius);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
@@ -648,7 +635,7 @@ class XRPlayerManager {
simpleCreateVideoBox = (boxId) => { //在相机聚焦位置创建一个初始视频框
let textBox = new EmbeddedVideoBox(boxId);
- let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
+ let position = this.getCameraPosition().clone().normalize().multiplyScalar(-this.radius);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
@@ -810,18 +797,21 @@ class XRPlayerManager {
2. stop或自动结束之后再调用start重播
params的格式:
{
- pos0, pos1, duration, 必需
+ start, end, duration, 必需
easing, callback 非必需(easing是速度变化的方式,详见https://www.createjs.com/docs/tweenjs/classes/Ease.html)
}
- pos0、pos1的格式
+ start、end的格式
{
lat, lon, 必需
- fov 非必需
+ fov, 非必需
+ distance 非必需
}或
{
x, y, z, 必需
- fov 非必需
+ fov, 非必需
+ distance 非必需
}
+ 可加入自定义的变量,并通过设置onUpdate使用这些变量
*/
getCameraAnimationList = () => {
if (this.senceConfig && this.senceConfig.hasOwnProperty('auto_guide_list')) {
@@ -841,7 +831,7 @@ class XRPlayerManager {
cameraTweens.push(animation);
});
var cameraTweenGroup = new CameraTweenGroup(cameraTweens,
- 500, this.innerViewControls);
+ this.radius, this.innerViewControls);
cameraTweenGroup.onCameraAnimationEnded = (key) => {
this.onCameraAnimationEnded &&
this.onCameraAnimationEnded(key);
@@ -855,59 +845,168 @@ class XRPlayerManager {
this.onCameraAnimationStop &&
this.onCameraAnimationStop(key);
}
- this.cameraTweenGroup = cameraTweenGroup;
+ this.playingCameraTweenGroup = cameraTweenGroup;
return cameraTweenGroup;
}
createCameraAnimation = (params) => {
- var cameraTween = new CameraTween(params, this.camera, 500,
+ var cameraTween = new CameraTween(params, this.camera, this.radius,
this.innerViewControls, this.cameraTweenStatus);
cameraTween.key = params.key;
return cameraTween;
}
setCameraTweenGroup = (cameraTweenGroup) => {
- this.cameraTweenGroup = cameraTweenGroup;
+ this.playingCameraTweenGroup = cameraTweenGroup;
}
getCameraTweenGroup = () => {
- return this.cameraTweenGroup;
+ return this.playingCameraTweenGroup;
}
startCameraTweenGroup = (time) => {
- if (!this.cameraTweenGroup) {
+ if (!this.playingCameraTweenGroup) {
return;
}
if (!!!time) {
- this.cameraTweenGroup.start();
+ this.playingCameraTweenGroup.start();
}
else {
- this.cameraTweenGroup.start(time);
+ this.playingCameraTweenGroup.start(time);
}
}
stopCameraTweenGroup = () => {
- this.cameraTweenGroup && this.cameraTweenGroup.stop();
+ this.playingCameraTweenGroup && this.playingCameraTweenGroup.stop();
}
pauseCameraTweenGroup = () => {
- this.cameraTweenGroup && this.cameraTweenGroup.pause();
+ this.playingCameraTweenGroup && this.playingCameraTweenGroup.pause();
}
playCameraTweenGroup = () => {
- this.cameraTweenGroup && this.cameraTweenGroup.play();
+ this.playingCameraTweenGroup && this.playingCameraTweenGroup.play();
}
nextCameraTween = () => {
- this.cameraTweenGroup && this.cameraTweenGroup.next();
+ this.playingCameraTweenGroup && this.playingCameraTweenGroup.next();
}
enableCameraTweenGroupAutoNext = (enable) => {
- this.cameraTweenGroup.enableAutoNext(enable);
+ this.playingCameraTweenGroup.enableAutoNext(enable);
}
enableCameraTweenGroupLoop = (enable) => {
- this.cameraTweenGroup.enableLoop(enable);
+ this.playingCameraTweenGroup.enableLoop(enable);
+ }
+
+ /****************************相机动画接口对接***********************************/
+ /**
+ * @description 选取当前位置为新的导览点并命名,并选择和上一个导览点的时间差(第一个点可忽略)
+ */
+ pickDirector = (name, duration=5000) => {
+ let pos = this.getCameraLatLon();
+ let fov = this.getCameraFov();
+ this.creatingDirectors.push({lat: pos.lat, lon: pos.lon, fov: fov, distance: this.radius, name: name});
+ this.directorDurations.push(duration);
+ }
+
+ /**
+ * @description 根据序号设置之前的导览点(从0开始),成功返回0,序号越界返回-1。
+ * @param {int} index 序号
+ * @param {Object} params 目标样式,包含lat, lon, fov, distance, name,不变的话可以不加进去
+ */
+ setDirector = (index, params) => {
+ if (index >= this.creatingDirectors.length) {
+ return -1;//序号越界
+ }
+ Object.assign(this.creatingDirectors[index], params);
+ return 0;
+ }
+
+ /**
+ * @description 返回导览点名字的序列
+ */
+ getDirectorNames = () => {
+ let names = [];
+ if (!!!this.playingCameraTweenGroup) {
+ return names;
+ }
+ this.playingCameraTweenGroup.cameraTweens.forEach((cameraTween) => {
+ let name = null;
+ if (cameraTween.pos0.hasOwnProperty('name')) {
+ name = cameraTween.pos0.name;
+ }
+ names.push(name);
+ });
+ const l = this.playingCameraTweenGroup.cameraTweens.length;
+ if (l > 1) {
+ let name = null;
+ if (this.playingCameraTweenGroup.cameraTweens[l - 1].pos1.hasOwnProperty('name')) {
+ name = this.playingCameraTweenGroup.cameraTweens[l - 1].pos1.name;
+ }
+ names.push(name);
+ }
+ return names;
+ }
+
+ /**
+ * @description 根据序号删除指定导览点,成功返回0,序号越界返回-1。
+ * @param {int} index 序号
+ */
+ deleteDirector = (index) => {
+ if (index >= this.creatingDirectors.length) {
+ return -1;//序号越界
+ }
+ this.creatingDirectors.splice(index, 1);
+ this.directorDurations.splice(index, 1);
+ return 0;
+ }
+
+ /**
+ * @description 清空所有导览点。
+ */
+ clearDirector = () => {
+ this.creatingDirectors = [];
+ return 0;
+ }
+
+ /**
+ * @description 根据当前选择的点创建演示序列。
+ */
+ createDemonstrateCameraTween = () => {
+ let tweenList = [];
+ if (this.creatingDirectors.length === 0) {//没有点
+ this.playingCameraTweenGroup = null;
+ return;
+ }
+ else if (this.creatingDirectors.length === 1) {//只有一个点
+ let oldPos = {}, newPos = {};
+ Object.assign(oldPos, this.creatingDirectors[0]);
+ Object.assign(newPos, this.creatingDirectors[0]);
+ tweenList.push(this.createCameraAnimation({
+ start: oldPos,
+ end: newPos,
+ duration: 1,
+ easing: "InOut"
+ }));
+ }
+ else {//有多个点
+ for (let i = 1; i < this.creatingDirectors.length; i++)
+ {
+ let oldPos = {}, newPos = {};
+ Object.assign(oldPos, this.creatingDirectors[i - 1]);
+ Object.assign(newPos, this.creatingDirectors[i]);
+ tweenList.push(this.createCameraAnimation({
+ start: oldPos,
+ end: newPos,
+ duration: this.directorDurations[i],
+ easing: "InOut"
+ }));
+ }
+ }
+ this.playingCameraTweenGroup = new CameraTweenGroup(tweenList,
+ this.radius, this.innerViewControls);
}
/**