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];
};