ss-dp/src/views/Home/MapCtrl/M3D/Map3D.js

265 lines
9.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { config } from "../../../../config";
import LayerMgr3D from './layermgr3d';
import BaseMap from '../basemap';
import { SatelliteImage3D } from "./layers/SatelliteImage3D";
import { Dem3D } from "./layers/Dem3D";
import { Tiles3D } from "./layers/Tiles3D";
import { Water3D } from "./layers/Water3D";
import { BouaLayer3D } from "./layers/BouaLayer3D";
import { BouaMaskLayer3D } from "./layers/BouaMaskLayer3D";
import { VillagesBouaLayer3D } from "./layers/VillagesBouaLayer3D"
import { getCameraViewPosition, getCameraViewCenter, getNewPosition } from './utils/cesutil'
const { Cesium } = window;
function __prepare_ces(dispatch) {
Cesium.CesiumWidget.prototype.showErrorPanel = function (title, error) {
dispatch && dispatch.map.setMode('2d');
if (title && title.indexOf('constructing') >= 0) {
alert('无法初始化三维场景如果一直出现此问题请尝试下载最新的chrome浏览器');
} else {
alert('三维场景渲染出现问题');
}
};
}
/**
* OL 封装
*/
export default class Map3D extends BaseMap {
constructor({ divid, dispatch, mapCenter }) {
super();
this.mapCenter = mapCenter;
this.dispatch = dispatch;
this.divid = divid; // div element id
this._map = null; // openlayers map obj
this.layerMgr = null;
this.toolMgr = null;
this.demo = null;
this.list = []
}
/**
* 初始化地图、图层
*/
init() {
__prepare_ces(this.dispatch);
const viewer = new Cesium.Viewer(this.divid, {
shouldAnimate: true, //动画
scene3DOnly: true,//用于强制场景以 3D 模式运行,禁止切换至 2D 或 Columbus 视图
animation: false,//获取动画小部件。
baseLayerPicker: false,//获取BaseLayerPicker。
geocoder: false,//获取地理编码器
sceneModePicker: false,//Gets the SceneModePicker.
fullscreenButton: false,
homeButton: false,
timeline: false,
navigationHelpButton: false,//导航帮助按钮
shadows: false,//确定阴影是否由光源投射。
infoBox: false,
skyAtmosphere: false,//去掉球边缘
selectionIndicator:false,//去掉选择指示器
});
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601('2000-01-01T04:00:07Z');//设置当前时间
//设置地表透明
let globe = viewer.scene.globe;
globe.depthTestAgainstTerrain = false;//关闭深度测试
//viewer.scene.skyAtmosphere.show = false; //关闭大气层阴影
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 100;
// viewer.scene.screenSpaceCameraController.maximumZoomDistance = 200000;
viewer.scene.globe.enableLighting = false; //关闭光照
viewer.scene.light.intensity = 6 //默认光源强度,太低了模型显示效果差
viewer.shadows = false;//关闭阴影
viewer.scene.globe.depthTestAgainstTerrain = false;//解决地形遮挡entity问题
//优化项--关闭相关特效
viewer.scene.moon.show = false; //月亮
viewer.scene.fog.enabled = false; //雾
viewer.scene.sun.show = false; //太阳
viewer.scene.skyBox.show = false; //天空盒
viewer.resolutionScale = 1.0; //画面细度默认值为1.0
viewer.scene.fxaa = false;
viewer.scene.postProcessStages.fxaa.enabled = true;
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;//设置球的基础色
viewer.scene.globe.undergroundColor= Cesium.Color.BLACK.withAlpha(0.5);//设置球的地下色
viewer.scene.backgroundColor = Cesium.Color.BLACK;
viewer.scene.screenSpaceCameraController.tiltEventTypes = [
Cesium.CameraEventType.RIGHT_DRAG, Cesium.CameraEventType.PINCH,
{ eventType: Cesium.CameraEventType.LEFT_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL },
{ eventType: Cesium.CameraEventType.RIGHT_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL }
];
viewer.scene.screenSpaceCameraController.zoomEventTypes = [
Cesium.CameraEventType.MIDDLE_DRAG, Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH
];
this.layerMgr = new LayerMgr3D(viewer);
this.getLayer3D(viewer)//加载地图
let lastPosition = {x:null,y:null,z:null};//记录上次移动坐标
let moveStartTime = Date.now();//记录上次setMapCenter事件, 用于防抖
let flag = false //帧检测移动后改为true
const timeInterval = 500; //防抖时间
viewer.scene.postRender.addEventListener(() => {
this.dispatch.runtime.tickViewChanged();
// this.layerMgr.frameUpdate();
const currentPos = viewer.camera.position
const { x, y, z } = lastPosition
if(currentPos.x===x && currentPos.y===y && currentPos.z===z){
if(flag && (Date.now() - moveStartTime >= timeInterval)){
const { lon, lat, height:olZoom } = getCameraViewCenter(viewer)||{};
console.log('3D',lon, lat, olZoom);
if(lon && lat && olZoom){
this.dispatch.runtime.setMapCenter({
center: [lon, lat],
zoom: olZoom,
pitch: config.pitch3d,
})
}
flag = false
moveStartTime = Date.now()
}
}else{
//在移动
lastPosition = { x: currentPos.x, y: currentPos.y, z: currentPos.z };
flag = true
}
});
let destination = Cesium.Cartesian3.fromDegrees(115.064,30.989,5000) //默认相机位置
if(this.mapCenter){
destination = getCameraViewPosition(this.mapCenter)
}
// 设置相机位置
viewer.camera.setView({
destination: destination,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(config.pitch3d),
roll: 0.0,
}
});
this._map = viewer;
const toremove = document.getElementsByClassName('cesium-widget-credits');
if (toremove && toremove[0]) {
toremove[0].style.display = 'none';
}
//地图移动完毕后设置位置
const {x, y, z} = viewer.camera.position
lastPosition = { x: x, y: y, z: z };
}
coordinateToPixel(lgtd, lttd, elev) {
if(!this._map){
return
}
const pt = Cesium.Cartesian3.fromDegrees(lgtd, lttd, elev);
const result = Cesium.SceneTransforms.worldToWindowCoordinates(
this._map.scene, pt);
if (!result) {
return null
}
return [result.x, result.y, pt.x, pt.y, pt.z];
}
/**
* 组件卸载时需要销毁map对象
*/
destroy() {
console.log('##############destroy##############');
if (!this.layerMgr) {
return;
}
this.layerMgr.destroy();
if (this._map) {
this._map.destroy();
this._map = null;
}
}
/**
* get layer obj
*/
getLayer(name) {
return this.layerMgr.getLayer(name);
}
zoomTo(cameraTarget={}) {
if (cameraTarget.center) {
if(cameraTarget.fixed){//固定相机朝向
const camera = this._map.camera;
const destination = getNewPosition(cameraTarget.center, cameraTarget.zoom, camera)
if(!destination){
return
}
camera.flyTo({
destination: destination,
orientation: {
heading: camera.heading,
pitch: camera.pitch,
roll: 0.0,
},
duration: 1,
});
}else{
this._map.camera.flyTo({
destination: getCameraViewPosition(cameraTarget),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(config.pitch3d),
roll: 0.0,
},
duration: 1.5, // 飞行时间,单位秒,可以根据需要调整
// 其他可选参数,例如:
// maximumHeight: 10000, // 最大高度
// pitchAdjustHeight : 1000, // 在飞行过程中调整俯仰角的高度阈值
// flyOverLongitude: 100, // 飞越经度,用于控制飞行路径
});
}
} else if (cameraTarget.bound) {
const b = cameraTarget.bound;
const p1 = Cesium.Cartesian3.fromDegrees(...b[0]);
const p2 = Cesium.Cartesian3.fromDegrees(...b[1]);
this._map.camera.flyToBoundingSphere(Cesium.BoundingSphere.fromPoints([p1, p2]));
}
}
async getLayer3D(viewer) {
Dem3D(viewer)//地形
SatelliteImage3D(viewer)//卫星地图
// Tiles3D(viewer)//倾斜摄影
// Water3D(viewer)//水面
VillagesBouaLayer3D(viewer)//乡镇边界
BouaLayer3D(viewer)//县界
BouaMaskLayer3D(viewer)//县界外遮罩层
}
}
// // 这是一个测试性能的工具留着
// let listenerExecutionTimes = []; // 记录每次执行的时间
// const start = performance.now();
// const end = performance.now();
// listenerExecutionTimes.push(end - start);
// setInterval(() => {
// if (listenerExecutionTimes.length > 0) {
// const avg = listenerExecutionTimes.reduce((a, b) => a + b, 0) / listenerExecutionTimes.length;
// console.log(`平均每帧监听函数执行时间: ${avg.toFixed(3)}ms`);
// listenerExecutionTimes = []; // 清空
// }
// }, 1000);