import * as THREE from 'three';
import InnerViewControls from '../controls/InnerViewControls';
import SpriteShapeHelper from '../display/SpriteShapeHelper';
import CenterModelHelper from '../display/CenterModelHelper';
import TWEEN from '@tweenjs/tween.js';
import ViewConvertHelper from '../action/ViewConvertHelper';
import TextureHelper from '../texture/TextureHelper';
import SpriteParticleHelper from '../display/SpriteParticleHelper';
import VRHelper from "./VRHelper";
import CameraMoveAction from "../action/CameraMoveAction";
import HotSpotHelper from '../display/HotSpotHelper';
import { CameraTween, CameraTweenGroup } from "../controls/CameraTween";
import EmbeddedBoxManager from "../display/ResourceBox/EmbeddedResource/EmbeddedBoxManager";
import EmbeddedTextBox from "../display/ResourceBox/EmbeddedResource/EmbeddedTextBox";
import EmbeddedImageBox from "../display/ResourceBox/EmbeddedResource/EmbeddedImageBox";
import EmbeddedVideoBox from "../display/ResourceBox/EmbeddedResource/EmbeddedVideoBox";
/**
* @class
* @name XRPlayerManager
* @description XR对外的交互通过Manager来提供
* @param {Element} mount Three.js 渲染过载节点
* @param {Object} initProps 初始化参数
* @param {Function} handler 统一的事件处理
* @return {XRPlayerManger} 管理器实例
* @example
* // 将在播放器创建完成之后,回调onCreated方法,参数为xrManager实例
* // 之后便可以在应用中通过xrManager来操作播放器
* <XRPlayer>
* onCreated={(xrManager)=>{this.manager = xrManager}}
* </XRPlayer>
*/
class XRPlayerManager {
constructor(mount, initProps, handler) {
this.mount = mount; // Threejs渲染挂载节点
this.props = initProps; // 初始化参数
this.handler = handler;
this.scene = null;
this.sceneMesh = null;
this.camera = null;
this.renderer = null;
this.controls = null;
this.sceneContainer = null; // 全景背景挂载节点
this.sceneTextureHelper = null; //全景场景纹理加载控制器
this.innerViewControls = null;
this.spriteShapeHelper = null;
this.spriteParticleHelper = null; // 粒子展示
this.centerModelHelper = null;
this.viewConvertHelper = null;
this.spriteEventList = null;
this.hotSpotHelper = null;
this.vrHelper = null;
// audio related
this.audio = document.createElement("audio");
this.audio.preload = "metadata";
document.body.appendChild(this.audio);
// camera animation related
this.cameraTweenStatus = {
num: 0,
paused: false
};
this.cameraTweenGroup = null;
this.onCameraAnimationEnded = null;
this.textHelper = null;
this.textBoxes = new Set();
this.senceConfig = null;
this.init();
}
init = () => {
this.initCamera();
this.initScene();
this.initRenderer();
this.initVR();
this.initTextHelper();
this.animate(0);
}
initCamera = () => {
const {
camera_fov, camera_far, camera_near,
camera_position: position, camera_target: target
} = this.props;
const camera = new THREE.PerspectiveCamera(
camera_fov, this.mount.clientWidth / this.mount.clientHeight,
camera_near, camera_far);
const renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer = renderer;
camera.position.set(position.x, position.y, position.z);
camera.target = new THREE.Vector3(target.x, target.y, target.z);
this.camera = camera;
this.innerViewControls = new InnerViewControls(this.camera);
}
initScene = () => {
const {
scene_texture_resource: textureResource,
axes_helper_display: isAxesHelperDisplay,
} = this.props;
const { panoramic_type = '360', radius = 500, height = 1000 } = textureResource;
this.sceneContainer = document.getElementById('video');
let geometry;
if (panoramic_type === '180') {
geometry = new THREE.CylinderGeometry(radius, radius, height, 40, 40, true); // 球体
} else {
geometry = new THREE.SphereBufferGeometry(radius, 80, 40); // 球体
}
geometry.scale(-1, 1, 1);
this.sceneTextureHelper = new TextureHelper(this.sceneContainer);
let texture = this.sceneTextureHelper.loadTexture(textureResource);
let material = new THREE.MeshBasicMaterial({ map: texture });
this.sceneMesh = new THREE.Mesh(geometry, material);
this.scene = new THREE.Scene();
this.scene.add(this.sceneMesh);
if (isAxesHelperDisplay) {
let axisHelper = new THREE.AxesHelper(1000)//每个轴的长度
this.scene.add(axisHelper);
}
this.scene.add(this.camera);
}
initRenderer = () => {
const renderer = this.renderer;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(this.mount.clientWidth, this.mount.clientHeight);
renderer.sortObjects = false;
renderer.autoClear = false;
this.mount.appendChild(renderer.domElement);
}
initVR = () => {
this.vrHelper = new VRHelper(this.renderer, this.camera);
this.vrHelper.setObjectInteractionHandler((pickedObject) => {
if (!!pickedObject) {
const key = pickedObject.name;
this.emitEvent(key, () => {
this.closeEffectContainer();
});
}
})
}
initTextHelper = () => {
// this.textHelper = new ResourceBoxHelper(this.innerViewControls.camera, this.renderer, this.sceneMesh, this.innerViewControls, this.mount);
this.embeddedBoxManager = new EmbeddedBoxManager(this);
}
animate = (time) => {
requestAnimationFrame(this.animate);
if (this.cameraTweenStatus.num === 0)
this.innerViewControls && this.innerViewControls.update();
if (this.centerModelHelper) {
this.centerModelHelper.update();
}
if (this.spriteParticleHelper) {
this.spriteParticleHelper.update();
}
if (this.cameraTweenStatus.paused === false)
TWEEN.update(); // 不要轻易去掉,渐变动画依赖该库
if (this.vrHelper.vrStatus) {
time *= 0.001;
if (this.spriteShapeHelper) {
let objects = this.spriteShapeHelper.getPointObjects();
this.vrHelper.updateInteractionObjects(objects, time);
}
this.vrHelper.render(this.scene, this.camera);
} else {
this.renderer.render(this.scene, this.camera);
}
if (this.hotSpotHelper) {
this.hotSpotHelper.update();
}
if (this.spriteShapeHelper) {
this.spriteShapeHelper.update();
}
this.textHelper && this.textHelper.update();
this.embeddedBoxManager && this.embeddedBoxManager.update();
}
/******************************配置导入导出******************************** */
/**
* @function
* @name XRPlayerManager#loadConfig
* @description 从一个配置对象中初始化整个场景
* @param {object}} config
*/
loadConfig = (config) => {
this.senceConfig = config;
if (config.hasOwnProperty('res_urls')) {
this.setSenceResource(config.res_urls[0]);
}
if (config.hasOwnProperty('camera_fov')) {
this.setCameraFov(config.camera_fov);
}
if (config.hasOwnProperty('fov_scope')) {
this.setFovHorizontalScope(config.fov_scope[0], config.fov_scope[1]);
this.setFovVerticalScope(config.fov_scope[2], config.fov_scope[3]);
}
if (config.hasOwnProperty('enable_auto_rotate')) {
this.setEnableAutoRotate(config.enable_auto_rotate);
if (config.hasOwnProperty('auto_rotate_speed')) {
this.setAutoRotateSpeed(config.auto_rotate_speed);
}
}
if (config.hasOwnProperty('volume')) {
this.setGlobalVolume(config.volume);
}
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('particle_effect')) {
this.setParticleEffectRes(config.particle_effect);
}
if (config.hasOwnProperty('model_list')) {
this.setModels(config.model_list);
}
if (config.hasOwnProperty('auto_guide_list')) {
this.createCameraTweenGroup(config.auto_guide_list, true);
}
}
/**
* @function
* @name XRPlayerManager#exportConfig
* @description 将当前场景的配置导出到配置对象中
* @returns {object} config
*/
exportConfig = () => {
let config = {};
config.res_urls = this.senceConfig.res_urls;
config.camera_fov = this.getCameraFov();
let hFovScope = this.getFovHorizontalScope();
let vFovScope = this.getFovVerticalScope();
config.fov_scope = [hFovScope.left, hFovScope.right, vFovScope.bottom, vFovScope.top];
config.enable_auto_rotate = this.getEnableAutoRotate();
config.auto_rotate_speed = this.getAutoRotateSpeed();
// 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.model_list = this.senceConfig.model_list;
config.particle_effect = this.senceConfig.particle_effect;
config.auto_guide_list = this.senceConfig.auto_guide_list;
return config;
}
/*****************************全局接口************************************ */
/**
* @function
* @name XRPlayerManager#setGlobalMuted
* @description 设置全局静音,会生成global_muted事件
* @param {boolean} muted 是否静音
*/
setGlobalMuted = (muted) => {
this.handler('global_muted', { muted: muted });
}
/**
* @function
* @name XRPlayerManager#setGlobalVolume
* @description 设置全局音量大小,会生成global_volume事件
* @param {int} volume 音量大小
*/
setGlobalVolume = (volume) => {
this.handler('global_volume', { volume: volume });
}
/****************************全景场景相关控制接口************************* */
setSenceResource = (res) => {
this.sceneTextureHelper && this.sceneTextureHelper.unloadResource();
this.sceneTextureHelper = new TextureHelper(this.sceneContainer);
let texture = this.sceneTextureHelper.loadTexture(res);
let material = new THREE.MeshBasicMaterial({ map: texture });
this.sceneMesh.material = material;
}
/**
* @function
* @name XRPlayerManager#startDisplaySenceResource
* @description 启动播放全景背景视频
*/
startDisplaySenceResource = () => {
if (this.sceneTextureHelper) {
this.sceneTextureHelper.startDisplay();
}
}
/**
* @function
* @name XRPlayerManager#pauseDisplaySenceResource
* @description 暂停播放全景背景视频
*/
pauseDisplaySenceResource = () => {
if (this.sceneTextureHelper) {
this.sceneTextureHelper.pauseDisplay();
}
}
/**
* @function
* @name XRPlayerManager#getDisplaySenceResourceCurrentTime
* @description 获取全景背景视频的当前播放时间
* @returns {number} currentTime
*/
getDisplaySenceResourceCurrentTime = () => {
return this.sceneContainer.currentTime;
}
// 自动旋转相关接口
getEnableAutoRotate = () => {
return this.innerViewControls.getEnableAutoRotate();
}
setEnableAutoRotate = (enable) => {
this.innerViewControls.setEnableAutoRotate(enable)
}
setAutoRotateSpeed = (speed) => {
this.innerViewControls.setAutoRotateSpeed(speed);
}
getAutoRotateSpeed = () => {
return this.innerViewControls.getAutoRotateSpeed();
}
setAutoRotateDirection = (direction) => {
this.innerViewControls.setAutoRotateDirection(direction);
}
/****************************热点标签相关控制接口************************* */
resetHotSpotsData = () => {
if (!this.spriteShapeHelper) {
this.spriteEventList = new Map();
this.spriteShapeHelper = new SpriteShapeHelper(this.scene,
this.camera, this.renderer, this.mount);
} else {
this.spriteEventList.clear();
}
}
setHotSpots = (hot_spot_list, event_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);
}
}
removeHotSpot = (hot_spot_key) => {
this.spriteShapeHelper.removeHotSpot(hot_spot_key);
}
setIsTipVisible = (enable) => {
this.spriteShapeHelper.setIsTipVisible(enable);
}
setHotSpotClickable = (enable) => {
this.spriteShapeHelper.setHotSpotClickable(enable);
}
/*****************************模型控制相关接口**************************** */
/**
* @function
* @name XRPlayerManager#resetModels
* @description reset模型相关的配置,会移除所有已经添加的模型
*/
resetModels = () => {
if (!this.centerModelHelper) {
this.centerModelHelper = new CenterModelHelper(this.scene);
} else {
this.centerModelHelper.removeAllModel();
}
}
/**
* @function
* @name XRPlayerManager#resetModels
* @param {array} model_list
* @description 通过一个模型列表,一次性添加多个模型到场景中
*/
setModels = (model_list) => {
this.resetModels();
this.centerModelHelper.loadModelList(model_list);
}
/**
* @function
* @name XRPlayerManager#addModel
* @param {string} model_key
* @param {object} model
* @description 通过key value的方式添加一个模型到场景中
*/
addModel = (model_key, model) => {
this.centerModelHelper.loadModel(model_key, model);
}
/**
* @function
* @name XRPlayerManager#removeModel
* @param {string} model_key
* @description 通过模型的key,移除之前添加的一个模型
*/
removeModel = (model_key) => {
this.centerModelHelper.removeModel(model_key);
}
/**
* @function
* @name XRPlayerManager#removeAllModel
* @description 移除所有之前添加的模型
*/
removeAllModel = () => {
this.centerModelHelper.removeAllModel();
}
/**************************相机移动相关接口************************* */
toNormalView = (durtime = 8000, delay = 0) => {
if (!this.viewConvertHelper) {
this.viewConvertHelper = new ViewConvertHelper(this.camera, this.innerViewControls);
}
this.innerViewControls.disConnect();
this.viewConvertHelper.toNormalView(durtime, delay);
}
toPlanetView = (durtime = 8000, delay = 0) => {
if (!this.viewConvertHelper) {
this.viewConvertHelper = new ViewConvertHelper(this.camera, this.innerViewControls);
}
this.innerViewControls.disConnect();
this.viewConvertHelper.toPlanetView(durtime, delay);
}
/**
* @function
* @name XRPlayerManager#moveCameraTo
* @param {*} descPos 相机目标位置,采用lat,lon表示
* @param {function} onStart 移动开始事件回调
* @param {functon} onEnd 移动结束事件回调
* @param {number} duration 相机移动动画的持续时长
* @param {number} delay 相机动画延迟启动时长
*/
moveCameraTo = (endPos, onStart, onEnd, duration = 5000, delay = 0) => {
if (!this.innerViewControls) return;
let startPos = this.innerViewControls.getCameraLatLonFovDisPosition();
var cameraMoveAction = new CameraMoveAction(startPos, endPos, duration, delay);
cameraMoveAction.onUpdateHandler = (pos) => {
this.innerViewControls.setCameraLatLonFovPosition(pos.lat, pos.lon, pos.fov, pos.distance);
}
cameraMoveAction.onStartHandler = () => {
this.innerViewControls && this.innerViewControls.disConnect();
onStart && onStart();
}
cameraMoveAction.onCompleteHandler = () => {
this.innerViewControls && this.innerViewControls.connect();
onEnd && onEnd();
}
cameraMoveAction.start();
}
/**************************相机控制相关接口************************* */
// 相机控制器开关
/**
* @function
* @name XRPlayerManager#connectCameraControl
* @description 连接相机视角控制器,视角可以通过鼠标等方式调整
*/
connectCameraControl = () => {
this.innerViewControls.connect();
}
/**
* @function
* @name XRPlayerManager#disConnectCameraControl
* @description 关闭连接器,无法通过鼠标方式调整视野
*/
disConnectCameraControl = () => {
this.innerViewControls.disConnect();
}
/**
* @function
* @name XRPlayerManager#enableKeyControl
* @description 视口开启键盘控制相机视角
* @param {boolean} enable
*/
enableKeyControl = (enable) => {
this.innerViewControls.enableKeyControl(enable);
}
// 方向传感器控制开关
getEnableOrientationControls = () => {
return this.innerViewControls.getEnableOrientationControls();
}
enableOrientationControls = () => {
this.innerViewControls.enableOrientationControls();
}
disableOrientationControls = () => {
this.innerViewControls.disableOrientationControls();
}
// 相机位置接口
getCameraPosition = () => {
return this.innerViewControls.getCameraPosition();
}
setCameraPosition = (x, y, z) => {
this.innerViewControls.setCameraPosition(x, y, z);
}
/**
* @function
* @name XRPlayerManager#getCameraLatLon
* @description 以lat,lon的方式获取相机的坐标
* @returns {object} latLonPos, lat【-180,180】,lon【0,180】
*/
getCameraLatLon = () => {
return this.innerViewControls.getCameraLatLonFovDisPosition();
}
/**
* @function
* @name XRPlayerManager#getCameraUVPosition
* @description 以UV坐标的方式获取球面映射到二维平面上的UV坐标
*/
getCameraUVPosition = () => {
let pos = this.getCameraLatLon();
let u = (180 - pos.lat) / 180;
let v = (pos.lon + 180) / 360;
return {
u: u,
v: v
}
}
// 相机当前fov接口
setCameraFov = (fov) => {
this.innerViewControls.setCameraFov(fov);
}
getCameraFov = () => {
return this.innerViewControls.getCameraFov();
}
enableChangeFov = (enable) => {
this.innerViewControls.enableChangeFov(enable);
}
// FOV上下范围设置接口
setFovVerticalScope = (bottom, top) => {
this.innerViewControls.setFovVerticalScope(bottom, top);
}
getFovVerticalScope = () => {
return this.innerViewControls.getFovVerticalScope();
}
// FOV左右范围设置接口
setFovHorizontalScope = (left, right) => {
this.innerViewControls.setFovHorizontalScope(left, right);
}
getFovHorizontalScope = () => {
return this.innerViewControls.getFovHorizontalScope();
}
/*******************************粒子特效接口********************************** */
setParticleEffectRes = (res) => {
if (!this.spriteParticleHelper) {
this.spriteParticleHelper = new SpriteParticleHelper(this.scene);
}
this.spriteParticleHelper.setResource(res);
}
getEnableParticleDisplay = () => {
return this.spriteParticleHelper.getEnableDisplay();
}
enableParticleDisplay = (enable) => {
if (enable) {
this.spriteParticleHelper.enableDisplay();
} else {
this.spriteParticleHelper.disableDisplay();
}
}
/*******************************VR接口********************************** */
changeVRStatus = () => {
if (this.vrHelper.vrStatus) {
this.vrHelper.disable();
this.renderer.setViewport(0, 0, this.mount.clientWidth, this.mount.clientHeight);
}
else {
this.vrHelper.enable();
}
}
/*******************************嵌入式文本框接口***************************** */
getEmbeddedBoxManager = () => {
return this.embeddedBoxManager;
}
simpleCreateTextBox = (boxId) => { //在相机聚焦位置创建一个初始文本框
let textBox = new EmbeddedTextBox(boxId);
textBox.setText('简易文本框');
let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
let theta = spherical.theta;
let lon = 90 - THREE.Math.radToDeg(theta);
let lat = 90 - THREE.Math.radToDeg(phi);
textBox.setPosition(lat, lon);
return textBox;
}
simpleCreateImageBox = (boxId) => { //在相机聚焦位置创建一个初始图片框
let textBox = new EmbeddedImageBox(boxId);
let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
let theta = spherical.theta;
let lon = 90 - THREE.Math.radToDeg(theta);
let lat = 90 - THREE.Math.radToDeg(phi);
textBox.setPosition(lat, lon);
return textBox;
}
simpleCreateVideoBox = (boxId) => { //在相机聚焦位置创建一个初始视频框
let textBox = new EmbeddedVideoBox(boxId);
let position = this.getCameraPosition().clone().normalize().multiplyScalar(-500);
const spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(position.x, position.y, position.z);
let phi = spherical.phi;
let theta = spherical.theta;
let lon = 90 - THREE.Math.radToDeg(theta);
let lat = 90 - THREE.Math.radToDeg(phi);
textBox.setPosition(lat, lon);
return textBox;
}
//快捷设置嵌入文本框的点击事件,如展示图片、视频、网页
simpleSetEmbeddedBoxEvent = (boxId, data) => {
let textBox = this.getEmbeddedBoxManager().getEmbeddedBox(boxId);
if (!!!textBox) return;
textBox.onClick(() => {
this.handler(data.type, { data }, () => {
this.closeEffectContainer();
});
});
}
/*******************************文本框接口********************************** */
setTextBoxText = (boxId, message) => { //改变文本框的内容
var params = {};
params.message = message;
this.textHelper.changeTextBox(boxId, params, this.scene);
}
setTextBoxSize = (boxId, width, height) => { //改变文本框的宽高
var params = {};
params.borderWidth = width;
params.borderHeight = height;
this.textHelper.changeTextBox(boxId, params, this.scene);
}
createTextBox = (boxId, params) => {
params.cameraPosition = this.getCameraPosition();
return this.textHelper.createTextBox(boxId, params, this.scene);
}
showTextBox = (boxId) => {
this.textHelper.showTextBox(boxId);
}
hideTextBox = (boxId) => {
this.textHelper.hideTextBox(boxId);
}
changeTextBox = (boxId, params) => {
this.textHelper.changeTextBox(boxId, params, this.scene);
}
//使用remove后记得将TextBox设为null,防止内存泄漏
removeTextBox = (boxId) => {
this.textHelper.removeTextBox(boxId, this.scene);
}
textBoxPlayVideo = (boxId) => {
this.textHelper.playVideo(boxId);
}
textBoxPauseVideo = (boxId) => {
this.textHelper.pauseVideo(boxId);
}
setTextBoxVideoVolume = (boxId, volume) => {
this.textHelper.setVideoVolume(boxId, volume);
}
addIcon = (img, position, name, title, width, height) => {
if (!this.hotSpotHelper) {
this.hotSpotHelper = new HotSpotHelper(this.scene, this.mount, this.camera);
}
const { x, y, z } = position;
this.hotSpotHelper.markIcon(img, new THREE.Vector3(x, y, z), name, title, width, height);
}
removeIcon = (name) => {
this.hotSpotHelper.removeIcon(name);
}
addIcons = (iconList) => {
this.hotSpotHelper.addIcons(iconList);
}
removeAllIcons = () => {
this.hotSpotHelper.removeAllIcons();
}
/********************************音频接口************************************/
initAudio = () => {
if (!this.audio) {
this.audio = document.createElement("audio");
this.audio.preload = "metadata";
document.body.appendChild(this.audio);
this.audio.onended = () => {
console.log('audio', "播放结束");
}
}
}
setAudioSrc = (src) => {
this.audio.setAttribute("src", src);
}
getAudioSrc = () => {
return this.audio.currentSrc;
}
setAudioVolume = (volume) => { // 0 到 1
this.audio.volume = volume;
}
getAudioVolume = () => {
return this.audio.volume;
}
setAudioMuted = (muted) => { // true 或 false
this.audio.muted = muted;
}
getAudioMuted = () => {
return this.audio.muted;
}
getAudioPaused = () => {
return this.audio.paused;
}
pauseAudio = () => {
this.audio.pause();
}
playAudio = () => {
this.audio.play();
}
playAudioRes = (src) => {
this.setAudioSrc(src);
this.audio.play();
}
replayAudio = () => {
this.audio.currentTime = 0;
}
endAudio = () => {
this.audio.currentTime = this.audio.duration;
}
/****************************相机动画接口***********************************/
/*
设置动画流程(示例见app.js):
1. 通过createCameraAnimation获取动画各部分的cameraTween
2. 通过setCameraAnimationGroup连接各动画
为防止不必要的bug,请遵循以下播放注意事项:(可以在以后设计UI时通过隐藏button或使button失效防止这一类问题产生)
1. startCameraAnimationGroup后才可调用stop,pause,play等功能
2. stop或自动结束之后再调用start重播
params的格式:
{
pos0, pos1, duration, 必需
easing, callback 非必需(easing是速度变化的方式,详见https://www.createjs.com/docs/tweenjs/classes/Ease.html)
}
pos0、pos1的格式
{
lat, lon, 必需
fov 非必需
}或
{
x, y, z, 必需
fov 非必需
}
*/
getCameraAnimationList = () => {
if (this.senceConfig && this.senceConfig.hasOwnProperty('auto_guide_list')) {
return this.senceConfig.auto_guide_list;
} else {
return [];
}
}
createCameraTweenGroup = (animationList, loop) => {
if (!!!loop) {
loop = false;
}
let cameraTweens = [];
animationList.forEach((item, index) => {
var animation = this.createCameraAnimation(item);
cameraTweens.push(animation);
});
var cameraTweenGroup = new CameraTweenGroup(cameraTweens,
100, this.innerViewControls);
cameraTweenGroup.onCameraAnimationEnded = (key) => {
this.onCameraAnimationEnded &&
this.onCameraAnimationEnded(key);
}
cameraTweenGroup.onCameraAnimationStart = (key) => {
this.onCameraAnimationStart &&
this.onCameraAnimationStart(key);
}
cameraTweenGroup.onCameraAnimationStop = (key) => {
this.onCameraAnimationStop &&
this.onCameraAnimationStop(key);
}
this.cameraTweenGroup = cameraTweenGroup;
return cameraTweenGroup;
}
createCameraAnimation = (params) => { //因为存在入场动画,导致设置相机动画时distance是450,这里直接改为100
var cameraTween = new CameraTween(params, this.camera, 100,
this.innerViewControls, this.cameraTweenStatus);
cameraTween.key = params.key;
return cameraTween;
}
setCameraTweenGroup = (cameraTweenGroup) => {
this.cameraTweenGroup = cameraTweenGroup;
}
getCameraTweenGroup = () => {
return this.cameraTweenGroup;
}
startCameraTweenGroup = (time) => {
if (!this.cameraTweenGroup) {
return;
}
if (!!!time) {
this.cameraTweenGroup.start();
}
else {
this.cameraTweenGroup.start(time);
}
}
stopCameraTweenGroup = () => {
this.cameraTweenGroup && this.cameraTweenGroup.stop();
}
pauseCameraTweenGroup = () => {
this.cameraTweenGroup && this.cameraTweenGroup.pause();
}
playCameraTweenGroup = () => {
this.cameraTweenGroup && this.cameraTweenGroup.play();
}
nextCameraTween = () => {
this.cameraTweenGroup && this.cameraTweenGroup.next();
}
enableCameraTweenGroupAutoNext = (enable) => {
this.cameraTweenGroup.enableAutoNext(enable);
}
enableCameraTweenGroupLoop = (enable) => {
this.cameraTweenGroup.enableLoop(enable);
}
/**
* @description 事件处理与分发
*/
emitEvent = (eventKey, callback = () => { }) => {
if (this.spriteEventList && this.spriteEventList.has(eventKey)) {
const data = this.spriteEventList.get(eventKey);
this.handler(data.type, { data }, () => {
callback();
})
} else {
callback();
}
}
closeEffectContainer = () => {
this.handler('close_effect_container');
}
/*******************************其他接口********************************** */
onWindowResize = (mountWidth, mountHeight) => {
this.camera.aspect = mountWidth / mountHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(mountWidth, mountHeight);
}
destroy = () => {
this.mount.removeChild(this.renderer.domElement)
this.sceneTextureHelper && this.sceneTextureHelper.unloadResource();
}
spherical2Cartesian = (lat, lon, distance) => {
let pos = { x: 0, y: 0, z: 0 };
const phi = THREE.Math.degToRad(90 - lat);
const theta = THREE.Math.degToRad(lon);
pos.x = distance * Math.sin(phi) * Math.cos(theta);
pos.y = distance * Math.cos(phi);
pos.z = distance * Math.sin(phi) * Math.sin(theta);
return pos;
}
}
export default XRPlayerManager;