/* 引入Cesium */ // import * as Cesium from 'Cesium'; //状态栏 import StatusBar from "./StatusBar.js"; import '../Assets/styles/base.css'; /** * 场景视图 */ class jtMap3d { /** * * 初始化三维大球 * @author joy * @param {Object} options 具有以下属性: * @param {String} options.container 包含球体小部件的 DOM 元素ID * @param {String} [options.imageryProviderType] 默认底图(世界影像)影像类型 * @param {String} [options.imageryProviderUrl] 默认底图(世界影像)影像路径 * * @example * * 例1: * const jtMap3d = new jtMap3d({container: "jtMap3dContainer"}); * * 例2: * const jtMap3d = new jtMap3d({ * container: "jtMap3dContainer", * imageryProviderType: "SingleTileImageryProvider", * imageryProviderUrl: "img/earth_3.jpg", * }); * */ constructor(options) { if (!Cesium.defined(options) || !Cesium.defined(options.container)) { throw new Cesium.DeveloperError("options.container is required."); } /* 设置token 这很重要 否则将导致地图无法加载 */ Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxNzM5YjQ3MC03YmMxLTRmMjAtOTk4Yi0yNDMyMDZlOTQzYTYiLCJpZCI6NTU5MjAsImlhdCI6MTYyNDI0NTM5NX0.diydVWFzw5C5rQlHaFYkdDJoSorcdex81KpWcntyICo'; /* 初始化地图控件 */ this._viewer = this._initMap(options); /* 初始化变量 地图基础图层集合*/ this._imageryLayers = this._viewer.imageryLayers; /* 初始化变量 地图原语集合 */ this._primitives = this._viewer.scene.primitives; /* 初始化变量 地图绘制实体集合 */ this._entities = this._viewer.entities; /* 初始化变量 数据源集合 */ this._dataSources = this._viewer.dataSources; //数据源集合 //默认天空盒子 this._defaultSkyBox = this._viewer.scene.skyBox; this.statusBar = new StatusBar(this._viewer); console.log(Cesium.buildModuleUrl.getCesiumBaseUrl()); } /** * 初始化球体查看小部件 * @ignore 忽略注释,注释不生成Doc * @param {Object} options 具有以下属性: * @param {Element | String} options.container 包含球体小部件的 DOM 元素或 ID * @param {String} [options.imageryProviderType] 影像类型 * @param {String} [options.imageryProviderUrl] 影像路径 * @return {Viewer} */ _initMap(options) { // //添加默认底图(世界影像) // var imageryProvider = new Cesium.SingleTileImageryProvider({ // url: 'jt3dSDK/imgs/earth_3.jpg', // }); // if (Cesium.defined(options.imageryProviderType)) { // if (Cesium.defined(options.imageryProviderUrl)) { // if (options.imageryProviderType == "SingleTileImageryProvider") { // imageryProvider = new Cesium.SingleTileImageryProvider({ // url: options.imageryProviderUrl, // }); // } else if (options.imageryProviderType == "OpenStreetMapImageryProvider") { // imageryProvider = new Cesium.OpenStreetMapImageryProvider({ // url: options.imageryProviderUrl // }); // } else if (options.imageryProviderType == "ArcGisMapServerImageryProvider") { // imageryProvider = new Cesium.ArcGisMapServerImageryProvider({ // url: options.imageryProviderUrl // }); // } // } else { // throw new Cesium.DeveloperError("imageryProviderType and imageryProviderUrl are required."); // } // } //球体查看器 let viewer = new Cesium.Viewer(options.container, { animation: true, //是否显示动画控件(左下角时间圆盘) timeline: true, //是否显示时间线控件(下方时间条),默认true shadows: false, //阴影,是否让太阳投射阴影 shouldAnimate: true, //是否允许动画,是否允许场景中的动画自动播放 baseLayerPicker: false, //地图切换控件(底图以及地形图)是否显示,默认显示true navigationHelpButton: false, //是否显示帮助信息控件,默认true homeButton: false, //主页按钮,默认true fullscreenButton: false, //全屏按钮,默认显示true sceneModePicker: false, //是否显示3D/2D选择器 scene3DOnly: true, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源 infoBox: false, //点击要素之后显示的信息,默认true clampToGround: true, //开启贴地 geocoder: false, //地名查找,默认true // imageryProvider: imageryProvider, selectionIndicator: false, //选中元素显示,默认true选中元素显示,默认true contextOptions: { webgl: { alpha: true, depth: true, stencil: true, antialias: true, premultipliedAlpha: true, //通过canvas.toDataURL()实现截图需要将该项设置为true preserveDrawingBuffer: true, failIfMajorPerformanceCaveat: true } } }); //隐藏版本信息 viewer._cesiumWidget._creditContainer.style.display = "none"; //是否显示地球 viewer.scene.globe.show = true; //高程遮挡效果。地形不透明 地形检测,Cesium开启地形检测 /* 此项设置为true可以查看哪些内容掉到地下了 正常情况下设置为false 否则会导致绘制的点只能看见一半 */ viewer.scene.globe.depthTestAgainstTerrain = true; // 光照效果 viewer.scene.globe.enableLighting = false; //启动主动渲染 这样地图加载完成后停止渲染 可节省CPU的开支(开启,以防部分动态效果失效) viewer.scene.requestRenderMode = false; //是否显示帧FPS viewer.scene.debugShowFramesPerSecond = true; //是否隐藏大气圈,如果显示大气圈,自定义天空盒子无效 viewer.scene.skyAtmosphere.show = false; //是否显示星空(默认天空盒子) viewer.scene.skyBox.show = true; //是否显示太阳 viewer.scene.sun.show = true; //是否显示有月亮 viewer.scene.moon.show = false; //取消鼠标左键双击 viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); //右侧缺少一块(全屏按钮) // viewer.animation.container.style.visibility = 'hidden'; // viewer.timeline.container.style.visibility = 'hidden'; // 修改timeline时间 从儒略日改为北京时间 viewer.animation.viewModel.dateFormatter = localeDateTimeFormatter; viewer.animation.viewModel.timeFormatter = localeTimeFormatter; viewer.timeline.makeLabel = localeDateTimeFormatter; //ignoredate 忽略日期 function localeDateTimeFormatter(datetime, viewModel, ignoredate) { var julianDT = new Cesium.JulianDate(); Cesium.JulianDate.addHours(datetime, 8, julianDT); var gregorianDT = Cesium.JulianDate.toGregorianDate(julianDT); var objDT; if (ignoredate) { objDT = ''; } else { objDT = new Date(gregorianDT.year, gregorianDT.month - 1, gregorianDT.day); objDT = gregorianDT.year + '-' + objDT.toLocaleString('zh-cn', { month: 'short' }).split('月').join('-') + gregorianDT.day + ' '; if (viewModel || gregorianDT.hour + gregorianDT.minute === 0) { return objDT objDT += ''; } } let hour, minute, second; if (gregorianDT.hour < 10) { hour = `0${gregorianDT.hour}` } else { hour = gregorianDT.hour } if (gregorianDT.minute < 10) { minute = `0${gregorianDT.minute}` } else { minute = gregorianDT.minute } if (gregorianDT.second < 10) { second = `0${gregorianDT.second}` } else { second = gregorianDT.second } // var millisecond = Math.round(gregorianDT.millisecond); // return objDT + hour + ":" + minute + ":" + second+ ":" + millisecond; return objDT + hour + ":" + minute + ":" + second; } function localeTimeFormatter(time, viewModel) { return localeDateTimeFormatter(time, viewModel, true) } return viewer; } /** * 初始化大球视窗范围 * @ignore 忽略注释,注释不生成Doc * @param {Object} options 具有以下属性: * @param {Number} options.longitude 经度,以度为单位 * @param {Number} options.latitude 纬度,以度为单位 * @param {Number} [options.height=0.0] 椭球的高度,以米为单位 * @param {Number} [options.heading=0.0] 指向,默认值0.0(北) * @param {Number} [options.pitch=-90] 视角,默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.roll=0.0] 翻滚 */ _setView(options) { if (!Cesium.defined(options.longitude) && !Cesium.defined(options.latitude)) { throw new Cesium.DeveloperError("longitude and latitude are required."); } Cesium.Check.typeOf.number("longitude", options.longitude); Cesium.Check.typeOf.number("latitude", options.latitude); this._viewer.camera.setView({ //设置视图 设置相机位置、方向和变换。 //fromDegrees()将经纬度和高程转为世界坐标 摄像机在 WGS84(世界)坐标中的最终位置,或从自上而下视图可见的矩形。 destination: Cesium.Cartesian3.fromDegrees( options.longitude, options.latitude, options.height ), orientation: { //此视角为观察者/相机 Math.toRadians() 将角度换成弧度。 heading: Cesium.Math.toRadians(Cesium.defaultValue(options.heading, 0.0)), pitch: Cesium.Math.toRadians(Cesium.defaultValue(options.pitch, -90)), roll: options.roll, }, }); } /** * 获取中国范围坐标 * @ignore 忽略注释,注释不生成Doc */ _getChinaPostion() { return Cesium.Cartesian3.fromDegrees(116.435314, 40.960521, 10000000.0); } /** * 初始定位中国 * @ignore 忽略注释,注释不生成Doc */ _flytoChina() { this._viewer.camera.flyTo({ destination: this._getChinaPostion(), duration: 8 }); } } /** * 通用对外公开函数 */ Object.assign(jtMap3d.prototype, /** @lends jtMap3d.prototype */ { /** * 初始化大球视窗范围,锁定为中国范围 */ setViewChina: function() { this._setView({ longitude: 103.84, //经度 latitude: 31.15, //维度 height: 24000000, //高度 heading: 0, // 偏航 pitch: -90, // 俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 roll: 0.0 // 翻滚 }); }, /** * 初始化项目范围(即全图功能) * @param {Object} options 具有以下属性: * @param {Number} options.west=0.0 最西端的经度范围[-180.0,180.0] * @param {Number} options.south=0.0 最南端的纬度范围[-90.0,90.0] * @param {Number} options.east=0.0 最东端的经度范围[-180.0,180.0] * @param {Number} options.north=0.0 最北端的纬度范围[-90.0,90.0] * @param {Number} [options.isRemove=true] 定位完成后是否删除 * @param {Number} [options.duration=3] 飞行时间 * @param {Number} [options.heading=0] * @param {Number} [options.pitch=-90] * @param {Number} [options.range=0] */ fullMap: function(options) { return new Promise((resolve, reject) => { let _self = this; this._entities.removeById("fullMapRectangle"); // 初始化参数默认值 options.isRemove = Cesium.defaultValue(options.isRemove, true); options.duration = Cesium.defaultValue(options.duration, 3); options.heading = Cesium.defaultValue(options.heading, 0); options.pitch = Cesium.defaultValue(options.pitch, -90); options.range = Cesium.defaultValue(options.range, 0.0); //left,bottom,right,top (西,南,东,北) var rectangle = Cesium.Rectangle.fromDegrees(options.west, options.south, options.east, options.north); //定义一个实体对象 var fullMapEntity = this._entities.add({ id: "fullMapRectangle", name: "fullMapRectangle", rectangle: { coordinates: rectangle, material: Cesium.Color.GREEN.withAlpha(0), height: 10.0, outline: false } }); var flyPromise = this._viewer.flyTo(fullMapEntity, { duration: options.duration, //飞行时间 offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range }, }); flyPromise.then(function(flyPromise) { if (flyPromise) { //飞行成功后,是否移除该实体 if (options.isRemove) { fullMapEntity && (_self._entities.remove(fullMapEntity), fullMapEntity = null); } resolve(true); } }) .catch(function(error) { console.log(error); }); }); }, /** * 地图指北 */ setMapNorth() { let viewer = this._viewer; let pitch = Cesium.Math.toDegrees(viewer.camera.pitch).toFixed(0); // 中心点位置 var center = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2)); var curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(center); let centerX = curPosition.longitude * 180 / Math.PI; let centerY = curPosition.latitude * 180 / Math.PI; //相机姿态信息 let cameraPointX = viewer.camera.positionCartographic.longitude * 180 / Math.PI; let cameraPointY = viewer.camera.positionCartographic.latitude * 180 / Math.PI; let cameraPointZ = viewer.camera.positionCartographic.height.toFixed(0); // 计算两点之间距离 var satrt = Cesium.Cartographic.fromDegrees(cameraPointX, cameraPointY, cameraPointZ); var end = Cesium.Cartographic.fromDegrees(centerX, centerY, 0); var geodesic = new Cesium.EllipsoidGeodesic(); geodesic.setEndPoints(satrt, end); var distance = geodesic.surfaceDistance; let range = Math.sqrt(Math.pow(distance, 2) + Math.pow(cameraPointZ - 0, 2)); // 创建旋转中心点 if (this.centerEntity) { viewer.entities.remove(this.centerEntity); } this.centerEntity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(centerX, centerY, 0), point: { color: Cesium.Color.RED, pixelSize: 1 } }); //更新场景相关旋转、角度距离参数 let offset = new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(pitch), range); viewer.zoomTo(this.centerEntity, offset); }, /** * 地图自旋 * @param {Array/Cartesian3} points 绕点位置[lng,lat,height]经度,以度为单位,纬度,以度为单位 * @param {Object} options 具有以下属性: * @param {Number} [options.speed=30] 设定绕行一周花费时间 * @param {Number} [options.pitch] 设定相机角度,默认相机当前看点的角度,如果大于0那么则是从地底往上看,所以要为负值。-90(向下看,俯仰)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.height] 设定相机距离点的距离,默认相机当前视角高度 */ setMapSpinByPoint(points, options) { let _self = this; let viewer = this._viewer; if (!Cesium.defined(points)) { throw new Cesium.DeveloperError("points is required."); } options = options || {}; options.speed = Cesium.defaultValue(options.speed, 30); //绕点位置 var position = points; if (points instanceof Cesium.Cartesian3) { position = points; } else { position = Cesium.Cartesian3.fromDegrees(points[0], points[1], points[2] || 0); } // 为更直观地展示查询的位置,在点击处添加对应点 var entity = viewer.entities.add( new Cesium.Entity({ point: new Cesium.PointGraphics({ color: new Cesium.Color(1, 1, 0), pixelSize: 6, outlineColor: new Cesium.Color(0, 1, 1) }), position: position }) ) // 给定飞行一周所需时间,比如30s, 那么每秒转动度数 var angle = 360 / options.speed; // 相机的当前heading var initialHeading = viewer.camera.heading; // 相机的当前pitch,相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值 var pitch = viewer.camera.pitch if (options.pitch) { pitch = Cesium.Math.toRadians(options.pitch); } // 给定相机距离点多少距离飞行 var distance = viewer.camera.positionCartographic.height; if (options.height) { distance = options.height; } // 起始时间 var startTime = Cesium.JulianDate.fromDate(new Date()); // 结束时间,设置一个结束时间,意思是360秒之后时间结束 // var stopTime = Cesium.JulianDate.addSeconds(startTime,angle, new Cesium.JulianDate()); viewer.clock.startTime = startTime.clone(); // 开始时间 // viewer.clock.stopTime = stopTime.clone(); // 结速时间 viewer.clock.currentTime = startTime.clone(); // 当前时间 viewer.clock.clockRange = Cesium.ClockRange.CLAMPED; // 行为方式 viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK; // 时钟设置为当前系统时间; 忽略所有其他设置。 var Exection = function TimeExecution() { // 当前已经过去的时间,单位s var delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime); // 根据过去的时间,计算偏航角的变化 var heading = Cesium.Math.toRadians(delTime * angle) + initialHeading; viewer.scene.camera.setView({ destination: position, // 点的坐标 orientation: { heading: heading, pitch: pitch, } }); viewer.scene.camera.moveBackward(distance); if (Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime) >= 0) { viewer.clock.onTick.removeEventListener(Exection); } //监听点击事件 var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(function(click) { viewer.clock.onTick.removeEventListener(Exection); viewer.entities.remove(entity); }, Cesium.ScreenSpaceEventType.LEFT_DOWN); }; viewer.clock.onTick.addEventListener(Exection); }, }); /* 输出 */ export default jtMap3d;