import {deepMerge, getHeightToLevel, getLevelMiddleHeight} from "./util"; import CesiumEntity from "./base/cesium_entity"; export default (hnMap: any) => { const defaultOption = { // 经度 lat: 37.7979042, // 纬度 lng: 112.55074, // 缩放级别 level: 8, // 旋转角度 heading: 0, // 俯仰角度 pitch: -90, // 翻滚角度 roll: 0, mars3d_config: "", // 高德地图key gaode_key: "", // 天地图key tdt_key: "", // 路网GeoJSON数据 roadNetworkGeoJSON: null, // 思极key sj_app_key: "", sj_app_secret: "", sj_style: "aegis://styles/aegis/Streets-Raster512", sj_route_net: true, // Cesium配置 cesium_accessToken: "", cesium_terrainProvider: null, cesium_imageryProvider: null, }; class mars3d_map { map: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; // 图层集合 layerList: any = []; event: any = {}; level: any = null; private constructor(id: string, option: any) { this.layerList = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.map = new mars3d.Map(id, this.config); // 实时更新level this.map.on("cameraMoveEnd", (e: any) => { const height = this.map.getCameraView().alt; this.level = getHeightToLevel(height); }); } static async create(id: string, option: any) { const instance = new mars3d_map(id, option); // 返回一个 Promise,等待地图的 'load' 事件 await new Promise((resolve) => { resolve(); }); // 地图加载完成后,返回实例 return instance; } formatConfig(option: any) { const alt = getLevelMiddleHeight(option.level); // 根据level获取合适的高度 return { ...option.mars3d_config, control: { locationBar: {fps: true}, }, scene: { center: { lat: option.lat, lng: option.lng, alt: alt, heading: 360 - option.heading || 0, pitch: option.pitch || 0, roll: option.roll || 0, }, fxaa: true, requestRenderMode: true, // 显式渲染 }, }; } addLayer(layer: any) { if (this.layerList.find((v: any) => v.id === layer.id)) { console.error("已存在同名图层" + layer.id); } else { this.layerList.push(layer); this.map.addLayer(layer.layerEntity); return layer; } } getLayer(layerId: any) { return this.layerList.find((v: any) => v.id === layerId); } // 删除图层 removeLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { this.layerList = this.layerList.filter((v: any) => v.id !== layerId); layer.destroy(); } } // 清空图层 clearLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { layer.children = []; layer.clearEntity(); } } on(eventType: any, callback: any) { this.off(eventType); switch (eventType) { case "click": this.event[eventType] = (event: any) => { const point = mars3d.LngLatPoint.fromCartesian(event.cartesian); //转为经纬度 point.format(); // 经度、纬度、高度 const position = { lng: point.lng, lat: point.lat, alt: point.alt, }; callback(position); }; break; case "cameraMoveEnd": this.event[eventType] = (event: any) => { callback(event); }; break; } this.map.on(eventType, this.event[eventType]); } off(eventType: any) { if (this.event[eventType]) { this.map.off(eventType, this.event[eventType]); delete this.event[eventType]; } } /** * 获取当前视口的经纬度范围 * 返回参数 {xmin,xmax,ymin,ymax} * @returns {*} */ getExtent() { return this.map.getExtent(); } /** * 获取当前视高 * 返回参数 {alt} * @returns {any} */ getCameraView() { return this.map.getCameraView(); } flyToPoint(position: any) { const pos = new mars3d.LngLatPoint(position[0], position[1], position[2]); this.map.flyToPoint(pos); } closePopup() { this.map.closePopup(); } // 设置投影模式 2d/3d setMode(mode: any) { const obj: any = { "2d": Cesium.SceneMode.SCENE2D, "3d": Cesium.SceneMode.SCENE3D, }; this.map.scene.mode = obj[mode.toLowerCase()]; } } class gaode_map { map: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; // 图层集合 layerList: any = []; private constructor(id: any, option: any) { this.layerList = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.map = new AMap.Map(id, this.config); } static async create(id: string, option: any) { const instance = new gaode_map(id, option); // 返回一个 Promise,等待地图的 'load' 事件 await new Promise((resolve) => { resolve(); }); // 地图加载完成后,返回实例 return instance; } formatConfig(option: any) { return { viewMode: "2D", // 是否为3D地图模式 zoom: option.level, // 初始化地图级别 pitch: option.pitch, rotation: option.heading, rotateEnable: true, pitchEnable: true, terrain: true, // 开启地形图 center: [option.lng, option.lat], // 初始化地图中心点位置 }; } addLayer(layer: any) { if (this.layerList.find((v: any) => v.id === layer.id)) { console.error("已存在同名图层"); } else { this.layerList.push(layer); this.map.add(layer.layerEntity); return layer; } } getLayer(layerId: any) { return this.layerList.find((v: any) => v.id === layerId); } removeLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { layer.destroy(); this.layerList = this.layerList.filter((v: any) => v.id !== layerId); } } clearLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { layer.children = []; layer.clearEntity(); } } } class siji_map { id: any = null; map: any = null; geocodingTask: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; // 图层集合 layerList: any = []; event: any = {}; level: any = null; private constructor(id: any, option: any) { this.id = id; this.layerList = []; this.level = this.option.level; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.map = new SGMap.Map(this.config); this.geocodingTask = new SGMap.GeocodingTask(); this.map.on("moveend", (e: any) => this.updateMapParams(e)); // 地图移动完成 this.map.on("zoomend", (e: any) => this.updateMapParams(e)); // 地图缩放完成 this.map.on("pitchend", (e: any) => this.updateMapParams(e)); // 地图俯仰角度完成 } static async create(id: string, option: any) { const instance = new siji_map(id, option); // 返回一个 Promise,等待地图的 'load' 事件 await new Promise((resolve) => { instance.map.on("load", (e: any) => { // 路况展示 if (option.sj_route_net) { let roadNetLayer = new SGMap.RoadNetLayer({map: instance.map}); roadNetLayer.render(); } //添加天空图层 instance.map.addLayer({ id: "sky", type: "sky", paint: { "sky-type": "atmosphere", "sky-atmosphere-sun": [0, 0], "sky-atmosphere-sun-intensity": 15, }, }); // 加载地形(需要v3.1.0,且需要新的key和secret) // !instance.map.getSource('terrain') && instance.map.addSource('terrain',{ // type:'raster-dem', // url:"aegis://aegis.Terrain3D",//地形高程数据源名称 // tileSize:512, // // }) // instance.map.setTerrain({ // source:'terrain', // exaggeration:1,//地形夸张比例 // }) resolve(e); }); }); // 地图加载完成后,返回实例 return instance; } formatConfig(option: any) { return { container: this.id, style: option.sj_style || "aegis://styles/aegis/StreetsDark-v2", // 默认缩放层级 zoom: option.level, // 地图中心点 center: [option.lng, option.lat], // 地图默认字体 localIdeographFontFamily: "Microsoft YaHei Regular", }; } addLayer(layer: any) { if (this.layerList.find((v: any) => v.id === layer.id)) { console.error("已存在同名图层"); } else { if (this.map) { this.layerList.push(layer); // this.map.addLayer(layer.config); return layer; } } } getLayer(layerId: any) { return this.layerList.find((v: any) => v.id === layerId); } removeLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer.id) { this.layerList = this.layerList.filter((v: any) => v.id !== layerId); layer.destroy(); } } clearLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { layer.children = []; layer.clearEntity(); } } getExtent() { const data = this.map.getBounds(); return { xmin: data._sw.lng, ymin: data._sw.lat, xmax: data._ne.lng, ymax: data._ne.lat, }; } on(eventType: any, callback: any) { this.off(eventType); switch (eventType) { case "click": this.event[eventType] = (event: any) => { callback( { lng: event.lngLat.lng, lat: event.lngLat.lat, alt: event.lngLat.alt || 0, }, event ); }; break; case "dblclick": this.event[eventType] = (event: any) => { callback(event); }; break; case "cameraMoveEnd": this.event[eventType] = () => { this.map.on("moveend", (event: any) => callback(event)); // 地图移动完成 this.map.on("zoomend", (event: any) => callback(event)); // 地图缩放完成 this.map.on("pitchend", (event: any) => callback(event)); // 地图俯仰角度完成 }; this.event[eventType](); break; //镜头移动事件 case "moveend": this.event[eventType] = (event: any) => { callback(event); }; break; case "zoomend": //"levelend" this.event[eventType] = (event: any) => { callback(event); }; break; case "mouseenter": this.event[eventType] = (event: any) => { callback(event); }; break; case "mouseleave": this.event[eventType] = (event: any) => { callback(event); }; break; case "mousemove": this.event[eventType] = (event: any) => { callback(event); }; break; } this.map.on(eventType, this.event[eventType]); } off(eventType: any) { if (this.event[eventType]) { this.map.off(eventType, this.event[eventType]); delete this.event[eventType]; } } // 更新当前地图参数 private updateMapParams(e: any) { this.level = this.map.getZoom(); let viewPos = this.getExtent(); if (this.level !== this.option.level) { this.layerList.forEach((layer: any) => { layer.children.forEach((entity: any) => { entity.option.distanceDisplayCondition && layer.updateEntity(entity, viewPos); }); }); } else { return; } } } class cesium_map { map: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; layerList: any = []; event: any = {}; level: any = null; private globalClickHandler: any = null; // 新增:点击回调注册表 存储 { entityGraphic => clickHandler } private entityClickHandlers = new Map void>>(); // 数据源集合 // dataSources: any = new Cesium.CustomDataSource("hnMap_dataSources"); // // 数据源集合 - 改为初始化为数组 // dataSources: any[] = []; private constructor(id: any, option: any) { this.layerList = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); // 创建Viewer前确保Cesium已加载 if (typeof Cesium === "undefined") { throw new Error("Cesium未加载,请检查资源加载顺序"); } this.map = new Cesium.Viewer(id, this.config); // 离线影像瓦片 if (this.option.cesium_imageryProvider) { const provider = new Cesium.UrlTemplateImageryProvider({ url: this.option.cesium_imageryProvider + '/{z}/{x}/{y}.jpg', maximumLevel: 18, // ⚠️ 必须 ≤ 你实际生成的最大层级 minimumLevel: 0, credit: 'Offline Tiles' }); this.map.imageryLayers.addImageryProvider(provider); } // 离线注记瓦片 if (this.option.cesium_annotationProvider) { const annotationProvider = new Cesium.UrlTemplateImageryProvider({ url: this.option.cesium_annotationProvider + '/{z}/{x}/{y}.png', maximumLevel: 18, minimumLevel: 0, credit: 'Offline Annotation' }); this.map.imageryLayers.addImageryProvider(annotationProvider); } // 确保 dataSources 存在且是正确的类型 if (!this.map.dataSources) { this.map.dataSources = new Cesium.DataSourceCollection(); } // 隐藏版权信息 if (this.map._cesiumWidget && this.map._cesiumWidget._creditContainer) { this.map._cesiumWidget._creditContainer.style.display = "none"; } // 监听相机移动事件 this.map.camera.moveEnd.addEventListener(() => { const camera = this.map.camera; const cartographic = Cesium.Cartographic.fromCartesian(camera.position); // 获取相机位置的经纬度坐标 const height = cartographic.height; this.level = getHeightToLevel(height); // 触发cameraMoveEnd事件 if (this.event.cameraMoveEnd) { this.event.cameraMoveEnd(); } }); // 设置初始视图 const {lat, lng, level, heading, pitch, roll} = this.option; const alt = getLevelMiddleHeight(level); // 设置相机位置 const initialPosition = Cesium.Cartesian3.fromDegrees(lng, lat, alt); const initialOrientation = new Cesium.HeadingPitchRoll( Cesium.Math.toRadians(heading), Cesium.Math.toRadians(pitch), Cesium.Math.toRadians(roll) ); this.map.camera.setView({ destination: initialPosition, orientation: initialOrientation, }); // 在地图完全初始化后再添加路网 setTimeout(() => { this.addMars3dStyleRoadNetwork(); }, 100); // 初始化后设置全局点击监听 this.setupGlobalClickHandler(); } static async create(id: string, option: any) { const instance = new cesium_map(id, option); // 等待场景初始化完成 if (instance.map.scene.initializePromise) { await instance.map.scene.initializePromise; } // ===== 新增:等待初始地形加载完成 ===== const waitForTerrain = async () => { const scene = instance.map.scene; const terrainProvider = scene.terrainProvider; // 如果没有地形或使用椭球体,直接 resolve if ( !terrainProvider || terrainProvider instanceof Cesium.EllipsoidTerrainProvider ) { return; } try { // 获取当前视图范围的角点(或使用初始中心点周围采样) const camera = instance.map.camera; const rectangle = instance.map.camera.computeViewRectangle(); console.log(rectangle) if (rectangle) { // 采样视图矩形内的多个点(例如四角+中心) const positions = [ new Cesium.Cartographic(rectangle.west, rectangle.south), new Cesium.Cartographic(rectangle.east, rectangle.south), new Cesium.Cartographic(rectangle.east, rectangle.north), new Cesium.Cartographic(rectangle.west, rectangle.north), new Cesium.Cartographic( Cesium.Math.average(rectangle.west, rectangle.east), Cesium.Math.average(rectangle.south, rectangle.north) ), ]; // 等待这些点的地形高度加载完成 await Cesium.sampleTerrainMostDetailed(terrainProvider, positions); } else { // 如果 computeViewRectangle 失败(如俯视角度极端),采样中心点 const {lat, lng} = instance.option; const center = new Cesium.Cartographic( Cesium.Math.toRadians(lng), Cesium.Math.toRadians(lat) ); await Cesium.sampleTerrainMostDetailed(terrainProvider, [center]); } } catch (error) { console.warn("Terrain sampling failed during init:", error); // 即使失败也不阻塞,继续 resolve } }; // 等待地形就绪 await waitForTerrain(); return instance; } // 格式化配置 formatConfig(option: any) { const config: any = { scene3DOnly: true, // 只支持3D场景 geocoder: false, // 关闭地理编码器 baseLayerPicker: false, // 关闭基础图层选择器 fullscreenButton: false, // 关闭全屏按钮 // 优化渲染性能 contextOptions: { webgl: { alpha: true, antialias: true, preserveDrawingBuffer: true, powerPreference: "default", }, }, animation: false, // 关闭动画控件 timeline: false, // 关闭时间轴 navigationHelpButton: false, // 关闭导航帮助按钮 selectionIndicator: false, // 关闭选择指示器 homeButton: false, // 关闭主页按钮 shouldAnimate: true, // 允许动画 infoBox: false, // 打开信息框 terrain: Cesium.Terrain.fromWorldTerrain({ requestWaterMask: true, requestVertexNormals: true, }), }; // // 设置地形 - 兼容性处理 // if (option.cesium_terrainProvider) { // config.terrainProvider = option.cesium_terrainProvider; // } return config; } private setupGlobalClickHandler() { // 销毁旧的(防止重复) if (this.globalClickHandler) { this.globalClickHandler.destroy(); } this.globalClickHandler = new Cesium.ScreenSpaceEventHandler(this.map.canvas); this.globalClickHandler.setInputAction((movement: any) => { const pickedObject = this.map.scene.pick(movement.position); if (pickedObject && pickedObject.id) { const handlers = this.entityClickHandlers.get(pickedObject.id); if (handlers && handlers.length > 0) { handlers.forEach(handler => handler(movement)); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } // 模仿Mars3D的方式添加路网 private addMars3dStyleRoadNetwork() { // 方案0:使用GeoJSON数据(如果可用) if (this.option.roadNetworkGeoJSON) { this.addGeoJSONRoadNetwork(); return; } // 方案1:使用天地图矢量(如果可用) if (this.option.tdt_key) { this.addTiandituVectorLayer(); return; } // // 方案2:使用高德地图(如果可用) // if (this.option.gaode_key) { this.addGaodeVectorLayer(); // return; // } // 方案3:使用ArcGIS街道地图(最稳定) // this.addArcGISStreetLayer(); } // 添加GeoJSON格式的路网 private addGeoJSONRoadNetwork() { try { const geojsonData = this.option.roadNetworkGeoJSON; // 创建数据源 const roadDataSource = new Cesium.GeoJsonDataSource("RoadNetwork"); // 加载GeoJSON数据 roadDataSource .load(geojsonData, { stroke: Cesium.Color.fromCssColorString("#ff6b6b"), // 线条颜色 strokeWidth: 2, // 线条宽度 fill: Cesium.Color.fromCssColorString("rgba(255, 255, 255, 0)"), // 填充颜色 markerSymbol: "none", // 不显示点标记 }) .then(() => { // 添加到地图 this.map.dataSources.add(roadDataSource); console.log("GeoJSON路网添加成功"); }) .catch((error: any) => { console.error("GeoJSON路网加载失败:", error); // 如果GeoJSON加载失败,使用备用方案 this.addTiandituVectorLayer(); }); } catch (error: any) { console.error("GeoJSON路网添加失败:", error); // 如果GeoJSON添加失败,使用备用方案 this.addTiandituVectorLayer(); } } // 添加天地图矢量图层 - 仅作为道路标注叠加层 private addTiandituVectorLayer() { try { const tdtKey = this.option.tdt_key; const sktKey = this.option.tdsk_key; // 降级到传统TK验证方式 console.warn("未配置tdsk_key,尝试使用传统TK验证方式(可能受限)"); // 天地图注记图层 - 包含道路名称等信息(半透明叠加) const tdtCva = new Cesium.WebMapTileServiceImageryProvider({ url: `https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={TileCol}&y={TileRow}&l={TileMatrix}&tk=${tdtKey}`, layer: "cva", style: "default", format: "tiles", tileMatrixSetID: "GoogleMapsCompatible", maximumLevel: 18, credit: new Cesium.Credit("天地图"), }); // 添加到现有图层之上,作为叠加层 const cvaLayer = this.map.imageryLayers.addImageryProvider(tdtCva); this.map.imageryLayers.raiseToTop(cvaLayer); console.log("天地图路网标注添加成功(TK验证)"); } catch (error) { console.error("天地图路网添加失败:", error); this.addArcGISStreetLayer(); } } // 添加高德矢量图层 private addGaodeVectorLayer() { try { // 高德路网图层 - 仅包含道路信息 // const gaodeRoadNet = new Cesium.UrlTemplateImageryProvider({ // url: `https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}`, // // url: `https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}`, // subdomains: ["1", "2", "3", "4"], // minimumLevel: 1, // maximumLevel: 18, // credit: new Cesium.Credit("高德卫星影像"), // }); // 再加上高德影像注记地图 const gaodeRoadBZ = new Cesium.UrlTemplateImageryProvider({ url: `https://webst0{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}`, // url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8", subdomains: ["1", "2", "3", "4"], minimumLevel: 1, maximumLevel: 18, credit: new Cesium.Credit("高德注记"), }); // 添加到现有图层之上 // const layer = this.map.imageryLayers.addImageryProvider(gaodeRoadNet); const layer_bz = this.map.imageryLayers.addImageryProvider(gaodeRoadBZ); // const layer_road = this.map.imageryLayers.addImageryProvider(roadLayer); // this.map.imageryLayers.raiseToTop(layer); this.map.imageryLayers.raiseToTop(layer_bz); // console.log("高德路网添加成功"); } catch (error) { console.error("高德路网添加失败:", error); this.addArcGISStreetLayer(); } } // 添加ArcGIS街道图层(最可靠的替代方案) private addArcGISStreetLayer() { try { // ArcGIS World Street Map - 包含详细道路 const arcgisStreets = new Cesium.ArcGisMapServerImageryProvider({ url: "https://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer", tileDiscardPolicy: undefined, enablePickFeatures: false, credit: new Cesium.Credit("Esri", false), }); // 不清除现有图层,而是直接添加到顶部 const layer = this.map.imageryLayers.addImageryProvider(arcgisStreets); this.map.imageryLayers.raiseToTop(layer); console.log("ArcGIS街道路网添加成功"); } catch (error) { console.error("ArcGIS街道添加失败:", error); // 即使失败也继续,避免覆盖现有的底图 console.warn("ArcGIS服务不可用,保持当前底图"); } } // 添加图层 addLayer(layer: any) { if (this.layerList.find((v: any) => v.id === layer.id)) { console.error("已存在同名图层" + layer.id); return null; } this.layerList.push(layer); switch (layer.type) { case "pointCloud": layer.addToScene(this.map) break default : const entity = layer.layerEntity; // 处理不同类型的图层实体 if (entity) { if ( entity instanceof Cesium.CustomDataSource || entity instanceof Cesium.DataSource ) { // 数据源类型 try { this.map.dataSources.add(entity); } catch (error) { console.error("添加数据源失败:", error); // 尝试重新添加 setTimeout(() => { try { this.map.dataSources.add(entity); } catch (retryError) { console.error("重新添加数据源也失败:", retryError); } }, 100); } } else if ( entity instanceof Cesium.Primitive || entity instanceof Cesium.PrimitiveCollection ) { // 图元类型 this.map.scene.primitives.add(entity); } else if (entity instanceof Cesium.Entity) { // 单个实体 this.map.entities.add(entity); } } break } return layer; } // 获取图层 getLayer(layerId: any) { return this.layerList.find((v: any) => v.id === layerId); } // 删除图层 removeLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { const entity = layer.layerEntity; if (entity && this.map) { if (entity instanceof Cesium.DataSource) { if ( this.map.dataSources && typeof this.map.dataSources.remove === "function" ) { this.map.dataSources.remove(entity); } } else if ( entity instanceof Cesium.PrimitiveCollection || entity instanceof Cesium.Primitive ) { this.map.scene.primitives.remove(entity); } else if (entity instanceof Cesium.Entity) { this.map.entities.remove(entity); } else if (Array.isArray(entity)) { entity.forEach((item) => { if (item instanceof Cesium.Entity) { this.map.entities.remove(item); } }); } } this.layerList = this.layerList.filter((v: any) => v.id !== layerId); layer.destroy?.(); } } // 清空图层 clearLayer(layerId: any) { const layer = this.getLayer(layerId); if (layer) { layer.children = []; layer.clearEntity(); } } // 事件监听 on(eventType: any, callback: any) { this.off(eventType); switch (eventType) { case "click": this.event[eventType] = (movement: any) => { // 获取点击位置 const ray = this.map.camera.getPickRay(movement.position); if (!ray) return; const cartesian = this.map.scene.globe.pick(ray, this.map.scene); if (!cartesian) return; const cartographic = Cesium.Cartographic.fromCartesian(cartesian); const position = { lng: Cesium.Math.toDegrees(cartographic.longitude), lat: Cesium.Math.toDegrees(cartographic.latitude), alt: cartographic.height, }; callback(position); }; // 使用屏幕空间事件处理器 this.map.screenSpaceEventHandler.setInputAction((movement: any) => { this.event[eventType](movement); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); break; case "cameraMoveEnd": this.event[eventType] = (event: any) => { callback(event); }; break; case "mouseMove": this.event[eventType] = (movement: any) => { callback(movement); }; this.map.screenSpaceEventHandler.setInputAction((movement: any) => { this.event[eventType](movement); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); break; } } // 取消事件监听 off(eventType: any) { if (this.event[eventType]) { // 移除事件处理器 this.map.screenSpaceEventHandler.removeInputAction( Cesium.ScreenSpaceEventType.LEFT_CLICK ); delete this.event[eventType]; } } /** * 获取当前视口的经纬度范围 */ getExtent() { const camera = this.map.camera; const frustum = camera.frustum; // 计算视锥体的四个角点 const corners = [ new Cesium.Cartesian2(0, 0), new Cesium.Cartesian2(this.map.canvas.width, 0), new Cesium.Cartesian2(this.map.canvas.width, this.map.canvas.height), new Cesium.Cartesian2(0, this.map.canvas.height), ]; let minLon = 180; let maxLon = -180; let minLat = 90; let maxLat = -90; corners.forEach((corner) => { const ray = camera.getPickRay(corner); if (!ray) return; const cartesian = this.map.scene.globe.pick(ray, this.map.scene); if (!cartesian) return; const cartographic = Cesium.Cartographic.fromCartesian(cartesian); const lon = Cesium.Math.toDegrees(cartographic.longitude); const lat = Cesium.Math.toDegrees(cartographic.latitude); minLon = Math.min(minLon, lon); maxLon = Math.max(maxLon, lon); minLat = Math.min(minLat, lat); maxLat = Math.max(maxLat, lat); }); return { xmin: minLon, xmax: maxLon, ymin: minLat, ymax: maxLat, }; } /** * 获取当前相机视图 */ getCameraView() { const camera = this.map.camera; const position = camera.positionWC; const cartographic = Cesium.Cartographic.fromCartesian(position); return { lng: Cesium.Math.toDegrees(cartographic.longitude), lat: Cesium.Math.toDegrees(cartographic.latitude), alt: cartographic.height, heading: Cesium.Math.toDegrees(camera.heading), pitch: Cesium.Math.toDegrees(camera.pitch), roll: Cesium.Math.toDegrees(camera.roll), }; } /** * 飞向指定点 */ flyToPoint(position: any) { const [lng, lat, alt] = position; const cartesian = Cesium.Cartesian3.fromDegrees(lng, lat, alt); // 创建经纬度坐标点 this.map.camera.flyTo({ destination: cartesian, duration: 2, complete: () => { console.log("飞行动画完成"); }, }); } /** * 飞向指定区域 */ flyToExtent(extent: any) { const rectangle = Cesium.Rectangle.fromDegrees( extent.xmin, extent.ymin, extent.xmax, extent.ymax ); this.map.camera.flyTo({ destination: rectangle, duration: 2, }); } /** * 关闭所有弹窗 */ closePopup() { this.map.selectedEntity = null; this.map.trackedEntity = null; } /** * 设置投影模式 2d/3d */ setMode(mode: string) { const modes: any = { "2d": Cesium.SceneMode.SCENE2D, "3d": Cesium.SceneMode.SCENE3D, columbus: Cesium.SceneMode.COLUMBUS_VIEW, }; if (modes[mode.toLowerCase()]) { this.map.scene.mode = modes[mode.toLowerCase()]; } } /** * 销毁地图 */ destroy() { if (this.map) { this.map.destroy(); this.map = null; } } } const map: any = { mars3d: mars3d_map, gaode: gaode_map, siji: siji_map, cesium: cesium_map, }; return map[hnMap.mapType]; };