import {deepMerge, convertPosition} from "../util"; import CesiumPopup from "../base/cesium_popup"; export default (hnMap: any) => { const defaultOption = {}; class mars3d_class { type: any = "layer"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; children: any = null; layerEntity: any = null; constructor(option: any) { this.id = option.id; this.children = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.layerEntity = new mars3d.layer.GraphicLayer(this.config); // 创建图层 } formatConfig(option: any) { return option; } getEntity(id: any) { return this.children.find((v: any) => v.id === id); } addEntity(entity: any) { if (this.children.find((v: any) => v.id === entity.id)) { console.error("已存在同名图形" + entity.id); } else { this.children.push(entity); if (entity.type == "route") { this.layerEntity.addGraphic(entity.graphic); // 添加图形 entity.start(); } else if (entity.type == "pointCloud" || entity.type == "heatMap") { hnMap.map.map.addLayer(entity.layerEntity); } else if (entity.type == "cluster") { // 添加聚合图层到地图 hnMap.map.map.addLayer(entity.layerEntity); // 如果已有位置数据,立即设置 if (entity.option.position && entity.option.position.length > 0) { setTimeout(() => { entity.setPosition(entity.option.position); entity.flyTo(); }, 100); } } else { this.layerEntity.addGraphic(entity.graphic); // 添加图形 } } } removeEntity(entityParam: any) { const entity = this.getEntity(entityParam); if (entity) { this.children = this.children.filter((v: any) => { return v.id !== entity.id; }); if ( entity.type === "pointCloud" || entity.type === "heatMap" || entity.type === "cluster" ) { hnMap.map.map.removeLayer(entity.id); } this.layerEntity.removeGraphic(entity.graphic); } } clearEntity() { this.children.forEach((v: any) => v.destroy()); this.children = []; this.layerEntity.clear(); } destroy() { this.clearEntity(); this.layerEntity.remove(true); hnMap.map.layerList = hnMap.map.layerList.filter( (v: any) => v.id !== this.id ); } show() { this.layerEntity.show = true; } hide() { this.layerEntity.show = false; } flyTo() { this.layerEntity.flyTo(); } /** * 飞向指定的多个图形 * @param entities */ flyToCustomEntities(entities: any) { // 计算所有线的最小最大坐标 let minLon = 180, maxLon = -180, minLat = 90, maxLat = -90; entities.forEach((line: any) => { line.graphic.positions.forEach((pos: any) => { const carto = mars3d.Cesium.Cartographic.fromCartesian(pos); const lon = mars3d.Cesium.Math.toDegrees(carto.longitude); const lat = mars3d.Cesium.Math.toDegrees(carto.latitude); minLon = Math.min(minLon, lon); maxLon = Math.max(maxLon, lon); minLat = Math.min(minLat, lat); maxLat = Math.max(maxLat, lat); }); }); // 飞到这个矩形范围 hnMap.map.map.flyToExtent({ xmin: minLon, xmax: maxLon, ymin: minLat, ymax: maxLat, }); } // 添加属性弹窗 addPopupByAttr() { this.layerEntity.bindPopup((event: any) => { if (event.graphic.attr) { const data = event.graphic.attr; return mars3d.Util.getTemplateHtml({ title: "详情", template: "all", attr: data, }); } }); } // 添加自定义dom弹窗 addCustomPopup(getCustomDom: any, option = {offsetY: -20}) { this.layerEntity.bindPopup(async (event: any) => { if (event.graphic.attr) { const data = event.graphic.attr || {}; const dom = await getCustomDom(data); if (dom) { return dom; } else { hnMap.map.closePopup(); } } }, option); } } class gaode_class { id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; children: any = null; layerEntity: any = null; // 创建全局信息窗口实例 propsInfoWindow: any = null; customInfoWindow: any = null; getCustomDom: any = null; constructor(option: any) { this.id = option.id; this.children = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); this.layerEntity = new AMap.OverlayGroup([]); // 创建图层 this.layerEntity.id = option.id; } formatConfig(option: any) { return option; } getEntity(entityParam: any) { return this.children.find((v: any) => v.id === entityParam); } addEntity(entity: any) { if (this.children.find((v: any) => v.id === entity.id)) { console.error("已存在同名图形" + entity.id); } else { this.children.push(entity); this.layerEntity.addOverlay(entity.graphic); // 添加图形 // 图层添加新图形后,需要重新调用绑定点击弹窗方法 if (this.propsInfoWindow) { this.addPopupByAttr(); } if (this.customInfoWindow) { // this.addCustomPopup() } } } removeEntity(entityParam: any) { const entity = this.getEntity(entityParam); if (entity) { this.children = this.children.filter((v: any): any => { return v.id !== entity.id; }); this.layerEntity.removeOverlay(entity.graphic); entity.destroy(); } } clearEntity() { this.children = []; this.layerEntity.clearOverlays(); } destroy() { this.clearEntity(); hnMap.map.map.remove(this.layerEntity); hnMap.map.layerList = hnMap.map.layerList.filter( (v: any) => v.id !== this.id ); } // 添加属性弹窗 addPopupByAttr() { if (!this.propsInfoWindow) { this.propsInfoWindow = new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30), }); } const handleClick = (e: any) => { const overlay = e.target; // 获取被点击的具体覆盖物 const data = overlay.getOptions().extData.data; let content = ""; for (const key in data) { content += `
${key}: ${data[key]}
`; } this.propsInfoWindow.setContent(content); this.propsInfoWindow.open(hnMap.map.map, e.lnglat); }; this.layerEntity.off("click", handleClick); this.layerEntity.on("click", handleClick); } // 添加自定义dom弹窗 addCustomPopup(getCustomDom: any) { if (!this.customInfoWindow) { this.customInfoWindow = new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30), }); } if (getCustomDom) { this.getCustomDom = getCustomDom; } const handleClick = (e: any) => { const overlay = e.target; // 获取被点击的具体覆盖物 const data = overlay.getOptions().extData.data; const dom = this.getCustomDom(data); this.customInfoWindow.setContent(dom); this.customInfoWindow.open(hnMap.map.map, e.lnglat); }; this.layerEntity.off("click", handleClick); this.layerEntity.on("click", handleClick); } } class siji_class { id = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; children: any = null; hideChildrenMap: any = null; layerEntity: any = null; infoWindow: any = null; entity: any = null; constructor(option: any) { this.id = option.id; this.children = []; this.hideChildrenMap = {}; deepMerge(this.option, option); this.config = this.formatConfig(this.option); } formatConfig(option: any) { return option; } updateEntity(entity: any, viewPos: any) { const isUpdateEntity = hnMap.map.level >= Number(entity.option.distanceDisplayCondition_far) && hnMap.map.level <= Number(entity.option.distanceDisplayCondition_near); if (isUpdateEntity) { if ( !entity.show && this.isIncludesLabel(entity.option.position, viewPos) ) { this.addLevelEntity(entity); } } else { if (entity.show) { this.removeLevelEntity(entity); } } } // 判断坐标是否在视口范围内 isIncludesLabel(p: any, viewPos: any) { return ( p[0] > viewPos.xmin && p[0] < viewPos.xmax && p[1] > viewPos.ymin && p[1] < viewPos.ymax ); } getEntity(id: any) { return this.children.find((v: any) => v.id === id); } addEntity(entity: any) { if (this.children.find((v: any) => v.id === entity.id)) { console.error("已存在同名图形" + entity.id); } else { this.children.push(entity); const isUpdateEntity = hnMap.map.level >= Number(entity.option.distanceDisplayCondition_far) && hnMap.map.level <= Number(entity.option.distanceDisplayCondition_near); if (!entity.option.distanceDisplayCondition || isUpdateEntity) { this.addLevelEntity(entity); } } } removeEntity(entityParam: any) { const entity = this.getEntity(entityParam); console.log(entity, "======88888====="); if (entity) { this.children = this.children.filter((v: any) => { return v.id !== entity.id; }); this.removeLevelEntity(entity); } } addLevelEntity(entity: any) { if (entity.type == "imagePoint") { hnMap.map.map.loadImage( entity.option.image, function (error: any, image: any) { entity.config.layout["icon-size"] = entity.option.width / image.width; entity.config.layout["icon-offset"] = [ entity.option.offset[0] / entity.config.layout["icon-size"], entity.option.offset[1] / entity.config.layout["icon-size"], ]; hnMap.map.map.addImage(entity.id + "_image", image); hnMap.map.map.addLayer(entity.config); } ); } else if (entity.type == "numPoint") { hnMap.map.map.addLayer(entity.config); hnMap.map.map.addLayer(entity.configLabel); } else if (entity.type == "divPoint") { entity.graphic.setLngLat(entity.option.position).addTo(hnMap.map.map); } else if (entity.type == "circle") { let featureArr = { type: "Feature", properties: { centerPoint: convertPosition(entity.option.position), radius: entity.option.radius, }, geometry: { type: "Polygon", coordinates: [], }, }; entity.graphic.addFeature(featureArr); // entity.graphic = new SGMap.DrawCircleHandler(entity.config); } else if (entity.type == "route") { hnMap.map.map.addLayer(entity.config_routeline); hnMap.map.map.addLayer(entity.config_routeplay); entity.createCar(); entity.chunkData = entity.joinLinePoint(); entity.start(); } else if (entity.type == "pointCloud") { hnMap.map.map.addLayer(entity.config); } else if (entity.type == "heatMap") { hnMap.map.map.addLayer(entity.config_heatmap); hnMap.map.map.addLayer(entity.config_point); hnMap.map.map.flyTo({ center: [ entity.option.position[0].lng, entity.option.position[0].lat, ], duration: 2000, essential: true, }); } else if (entity.type == "cluster") { hnMap.map.map.addLayer(entity.config_layer); hnMap.map.map.addLayer(entity.config_label); hnMap.map.map.loadImage( entity.option.image, function (error: any, image: any) { entity.config_Image.layout["icon-size"] = entity.option.width / image.width; hnMap.map.map.addImage(entity.id + "_poiImage", image); hnMap.map.map.addLayer(entity.config_Image); } ); hnMap.map.map.flyTo({ center: entity.option.position[0].position, duration: 2000, essential: true, }); } else { hnMap.map.map.addLayer(entity.config); } entity.show = true; } removeLevelEntity(entity: any) { if (entity) { if (entity.type == "circle") { entity.graphic.remove(); entity.graphic.clearData(); } else if (entity.type == "numPoint") { hnMap.map.map.removeLayer(entity.config.id); hnMap.map.map.removeSource(entity.config.id); hnMap.map.map.removeLayer(entity.configLabel.id); hnMap.map.map.removeSource(entity.configLabel.id); } else if (entity.type == "divPoint") { entity.graphic.remove(); } else if (entity.type == "route") { hnMap.map.map.removeLayer(entity.config_routeline.id); hnMap.map.map.removeSource(entity.config_routeline.id); hnMap.map.map.removeLayer(entity.config_routeplay.id); hnMap.map.map.removeSource(entity.config_routeplay.id); entity.imgMarker.remove(); } else if (entity.type == "imagePoint") { hnMap.map.map.removeImage(entity.id + "_image"); hnMap.map.map.removeLayer(entity.id); hnMap.map.map.removeSource(entity.id); } else if (entity.type == "cluster") { console.log("cluster_siji_remove", entity); hnMap.map.map.removeLayer(entity.config_layer.id); hnMap.map.map.removeLayer(entity.config_label.id); hnMap.map.map.removeImage(entity.id + "_poiImage"); hnMap.map.map.removeLayer(entity.config_Image.id); hnMap.map.map.removeSource(entity.id); // hnMap.map.map.removeLayer(entity.id); } else { hnMap.map.map.removeLayer(entity.id); hnMap.map.map.removeSource(entity.id); } entity.show = false; } } // 控制图层层高 moveEntity(layerIds: Array) { // 数组转字符串 let s = layerIds.join(","); hnMap.map.map.moveLayer(s); } clearEntity() { this.children.forEach((v: any) => { this.removeEntity(v.id); }); this.children = []; } destroy() { this.clearEntity(); hnMap.map.layerList = hnMap.map.layerList.filter( (v: any) => v.id !== this.id ); console.log("销毁图层", hnMap.map.layerList); } // 添加属性弹窗 addPopupByAttr() { // 如果已有弹窗,先关闭 this.removePopup(); this.infoWindow = new SGMap.Popup({ offset: {bottom: [0, 0]}, className: "my-attrPopup-class", }); const handleClick = (e: any) => { let data = e.features[0].properties; // 创建弹窗内容 let content = ""; for (const key in data) { content += `
${key}: ${data[key]}
`; } this.infoWindow.setHTML(content); this.infoWindow.setLngLat(e.lngLat).addTo(hnMap.map.map); }; hnMap.map.map.on("click", this.config.id, handleClick); } // 添加自定义dom弹窗 addCustomPopup(getCustomDom: any) { // 如果已有弹窗,先关闭 this.removePopup(); this.infoWindow = new SGMap.Popup({ offset: {bottom: [0, 0]}, className: "my-customPopup-class", }); const handleClick = (e: any) => { const data = e.features[0].properties; const dom = getCustomDom(data); this.infoWindow.setHTML(dom); this.infoWindow.setLngLat(e.lngLat).addTo(hnMap.map.map); }; hnMap.map.map.on("click", this.config.id, handleClick); } // 弹窗删除 removePopup() { if (this.infoWindow) { this.infoWindow.remove(); } } } class cesium_class { type: any = "layer"; id: any = null; option: any = JSON.parse(JSON.stringify(defaultOption)); config: any = null; children: any = null; layerEntity: any = null; show: boolean = true; /** 事件监听器集合 */ event: Record = {}; /** 屏幕空间事件处理器 */ screenSpaceEventHandler: any = null; /** 弹窗实例 */ popup: any = null; /** 弹窗内容缓存 */ popupContent: string | null = null; /** 是否显示弹窗 */ showPopupOnClick: boolean = false; /** 弹窗样式配置 */ popupStyle: any = null; constructor(option: any) { this.id = option.id; this.children = []; deepMerge(this.option, option); this.config = this.formatConfig(this.option); // 创建数据源 - 使用更可靠的创建方式 try { if (typeof Cesium !== "undefined") { this.layerEntity = new Cesium.CustomDataSource(this.id); this.layerEntity.show = this.show; // 确保地图对象存在 if (hnMap && hnMap.map && hnMap.map.map) { const viewer = hnMap.map.map; // 检查是否是 Cesium.Viewer 实例 if (viewer instanceof Cesium.Viewer) { viewer.dataSources.add(this.layerEntity); } else { // 备用方案:使用其他方式添加 if (viewer.entities) { // 如果地图有 entities 属性,直接使用 this.layerEntity = viewer.entities; } } } } else { console.error("Cesium 未加载"); this.layerEntity = {entities: []}; // 创建空的占位对象 } } catch (error) { console.error("创建数据源失败:", error); this.layerEntity = {entities: []}; // 创建空的占位对象 } // 创建弹窗实例 if (hnMap && hnMap.map && hnMap.map.map) { const PopupClass = CesiumPopup(hnMap); this.popup = new PopupClass(hnMap.map.map, {style: this.popupStyle}); } } formatConfig(option: any) { return option; } addEntity(entity: any) { if (this.children.find((v: any) => v.id === entity.id)) { console.error(`已存在同名图形: ${entity.id}`); return; } this.children.push(entity); // 根据实体类型进行不同的处理 switch (entity.type) { case "polygon": this.handlePolygon(entity); break; case "route": this.handleRoute(entity); break; case "cluster": this.handleCluster(entity); break; case "heatMap": this.handleHeatMap(entity); break; default: // 默认处理:添加到数据源 if (entity.graphic && entity.graphic instanceof Cesium.Entity) { this.layerEntity.entities.add(entity.graphic); } else if (entity.graphic) { // 非标准 Entity 对象 this.addGenericEntity(entity); } break; } } // 处理多边形 handlePolygon(entity: any) { // console.log("处理多边形:", entity.id); if (entity.polygonEntity) { this.layerEntity.entities.add(entity.polygonEntity); // console.log("多边形实体已添加到图层数据源"); } if (entity.outlineEntity) { this.layerEntity.entities.add(entity.outlineEntity); // console.log("边框实体已添加到图层数据源"); } entity.layer = this; } // 处理路径 handleRoute(entity: any) { // console.log("处理路径:", entity.id); if (entity.graphic) { setTimeout(() => { entity.start(); }, 100); } entity.layer = this; } // 处理集群 handleCluster(entity: any) { console.log("处理集群:", entity.id, entity); entity.layer = this; // 将聚合数据源添加到地图中 if ( entity.clusterDataSource && hnMap.map.map && hnMap.map.map.dataSources ) { // 检查是否已经添加过了 let isAdded = false; for (let i = 0; i < hnMap.map.map.dataSources.length; i++) { if (hnMap.map.map.dataSources.get(i).name === entity.id) { isAdded = true; break; } } if (!isAdded) { hnMap.map.map.dataSources.add(entity.clusterDataSource); } } // 集群有自己的管理逻辑 if (entity.option.position && entity.option.position.length > 0) { setTimeout(() => { entity.setPosition(entity.option.position); entity.flyTo({ // 为聚合点设置合适的飞行参数 duration: 2.0, pitch: -45, // 设置俯仰角避免过于垂直 radiusMultiplier: 3.0, // 增加视野范围 }); }, 100); } } // 处理热力图 handleHeatMap(entity: any) { console.log("处理热力图:", entity.id, entity); entity.flyTo(); } // 添加通用实体 addGenericEntity(entity: any) { try { // 尝试将 graphic 转换为 Cesium.Entity if (entity.graphic.id && entity.graphic.position) { const cesiumEntity = new Cesium.Entity(entity.graphic); this.layerEntity.entities.add(cesiumEntity); } else { console.warn("实体没有有效的 graphic 属性:", entity); } } catch (error) { console.error("添加通用实体失败:", error); } } removeEntity(entityParam: string) { const entity = this.getEntity(entityParam); if (entity) { this.children = this.children.filter((v: any) => v.id !== entity.id); // 根据实体类型进行不同的移除处理 switch (entity.type) { case "polygon": if (entity.polygonEntity) { this.layerEntity.entities.remove(entity.polygonEntity); } if (entity.outlineEntity) { this.layerEntity.entities.remove(entity.outlineEntity); } break; case "pointCloud": // 点云有自己的销毁逻辑 if (entity.destroy) { entity.destroy(); } break; case "cluster": // 聚合点图层有自己的销毁逻辑 if (entity.destroy) { entity.destroy(); } break; default: if (entity.graphic) { this.layerEntity.entities.remove(entity.graphic); } break; } if (entity.destroy) { entity.destroy(); } } } getEntity(entityId: any) { return this.children.find((v: any) => v.id === entityId); } clearEntity() { this.children.forEach((entity: any) => { // 特殊处理点云 if (entity.type === "pointCloud") { if (entity.destroy) { entity.destroy(); } } else { if (entity.destroy) { entity.destroy(); } if (entity.graphic) { try { this.layerEntity.entities.remove(entity.graphic); } catch (error) { console.warn("移除实体失败:", error); } } } }); this.children = []; } destroy() { this.clearEntity(); // 从地图移除数据源 if (hnMap && hnMap.map && hnMap.map.map) { const viewer = hnMap.map.map; // 检查是否是 Cesium.Viewer if ( viewer.dataSources && typeof viewer.dataSources.remove === "function" ) { try { viewer.dataSources.remove(this.layerEntity); } catch (error) { console.warn("移除数据源失败:", error); } } } // 从图层列表中移除 const index = hnMap.map.layerList.findIndex((v: any) => v.id === this.id); if (index > -1) { hnMap.map.layerList.splice(index, 1); } } // 添加属性弹窗 addPopupByAttr() { // 为图层中的所有实体添加弹窗功能 this.children.forEach((entity: any) => { if (entity.addPopupByAttr) { // 如果实体本身有添加弹窗的方法,直接调用 entity.addPopupByAttr(); } }); // 如果图层本身需要处理弹窗事件 if (this.layerEntity && hnMap && hnMap.map && hnMap.map.map) { // 创建屏幕空间事件处理器 if (!this.screenSpaceEventHandler) { this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler( hnMap.map.map.canvas ); } // 移除之前的点击事件 this.screenSpaceEventHandler.removeInputAction( Cesium.ScreenSpaceEventType.LEFT_CLICK ); // 添加点击事件监听 this.screenSpaceEventHandler.setInputAction((click: any) => { // 检查是否点击到了当前图层中的实体 const pickedObject = hnMap.map.map.scene.pick(click.position); if (pickedObject && pickedObject.id) { const entity = pickedObject.id; // 检查实体是否属于当前图层的数据源 if (this.layerEntity.entities.contains(entity)) { // 生成弹窗内容 let content = '
'; // 获取实体的属性数据 const properties = entity.properties || {}; for (const key in properties) { if (properties.hasOwnProperty(key)) { content += `
${ key + ": " + properties[key] }
`; } } content += "
"; if (content) { this.popup.show({cartesian: entity.position}, content); } } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } } // 添加自定义弹窗 addCustomPopup(getCustomDom: Function) { // 为图层中的所有实体添加自定义弹窗功能 this.children.forEach((entity: any) => { if (entity.addCustomPopup) { // 如果实体本身有添加自定义弹窗的方法,直接调用 entity.addCustomPopup(getCustomDom); } }); // 如果图层本身需要处理自定义弹窗事件 if (this.layerEntity && hnMap && hnMap.map && hnMap.map.map) { // 创建屏幕空间事件处理器 if (!this.screenSpaceEventHandler) { this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler( hnMap.map.map.canvas ); } // 移除之前的点击事件 this.screenSpaceEventHandler.removeInputAction( Cesium.ScreenSpaceEventType.LEFT_CLICK ); // 添加点击事件监听 this.screenSpaceEventHandler.setInputAction((click: any) => { // 检查是否点击到了当前图层中的实体 const pickedObject = hnMap.map.map.scene.pick(click.position); if (pickedObject && pickedObject.id) { const entity = pickedObject.id; // 检查实体是否属于当前图层的数据源 if (this.layerEntity.entities.contains(entity)) { // 获取实体的属性数据 const properties = entity.properties || {}; // 生成自定义弹窗内容 try { const customDom = getCustomDom(properties); if (customDom) { this.popup.show({cartesian: entity.position}, customDom); } } catch (error) { console.error("生成自定义弹窗内容失败:", error); } } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } } } const fn: any = { mars3d: mars3d_class, gaode: gaode_class, siji: siji_class, cesium: cesium_class, }; return fn[hnMap.mapType]; };