如何在cesium的地图上添加geojson数据,并计算中心点,在中心点打上图标和文字
效果图:
一、创建地图
js
import * as Cesium from "cesium";
Cesium.Ion.defaultAccessToken = key;
const viewer = new Cesium.Viewer(id);
二、加载geojson数据
使用Cesium.GeoJsonDataSource.load(file,option)
加载geojson文件、或者是geojson的数据,遍历每个区域使用viewer.entities.add()
用于添加中心点的图标。使用viewer.entities.remove(entity)
可以移除实体。
js
let lastAddedDataSource = null
let center = []
const dataSourcePromise = Cesium.GeoJsonDataSource.load(geoJsonObject, {
// 可选参数
clampToGround: true, // 使数据贴合地形
stroke: Cesium.Color.HOTPINK,
// fill: Cesium.Color.GREEN.withAlpha(0.5),
strokeWidth: 3,
});
dataSourcePromise
.then(function (dataSource) {
// 添加数据源到Viewer
viewer.dataSources.add(dataSource);
lastAddedDataSource = dataSource;
// 获取所有实体
const entities = dataSource.entities.values;;
// 遍历每个实体
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
// 读取properties信息
const properties = entity.properties;
//每个区域添加随机颜色
entity.polygon.material = Cesium.Color.fromRandom({
alpha: 0.7,
minimumRed: 0.1,
minimumGreen: 0.1,
minimumBlue: 0.1,
});
//中心点
const positions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
// 计算中心点
const centerPosition = computePolygonCentroid(positions);
// 在中心点添加图标
let point = viewer.entities.add({
id: id,
name: name,
position: centerPosition,
label: {
text: properties?.NAME?._value,
scale: 0.5,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, 40),
},
billboard: {
image: icon, // 图标路径
width: 50,
height: 50,
verticalOrigin: Cesium.VerticalOrigin.TOP,
disableDepthTestDistance: Number.POSITIVE_INFINITY, // 确保图标始终可见
pixelOffset: new Cesium.Cartesian2(0, -25),
},
monitoItems: {
省: properties["省"]?._value,
市: properties["市"]?._value,
县: properties["县"]?._value,
},
});
center.push(point);
}
// 自动缩放到数据范围
viewer.zoomTo(dataSource);
})
.catch(function (error) {
console.error("Error loading GeoJSON:", error);
});
计算中心点的方法
js
function computePolygonCentroid(positions) {
const cartographics = positions.map(p => Cesium.Cartographic.fromCartesian(p));
// 转换为经纬度坐标
const points = cartographics.map(c => {
return {
lon: Cesium.Math.toDegrees(c.longitude),
lat: Cesium.Math.toDegrees(c.latitude)
};
});
// 确保多边形是闭合的
if (points.length > 0 &&
(points[0].lon !== points[points.length-1].lon ||
points[0].lat !== points[points.length-1].lat)) {
points.push({...points[0]});
}
// 计算中心点
let area = 0;
let centroidLon = 0;
let centroidLat = 0;
for (let i = 0; i < points.length - 1; i++) {
const p1 = points[i];
const p2 = points[i + 1];
const f = p1.lon * p2.lat - p2.lon * p1.lat;
centroidLon += (p1.lon + p2.lon) * f;
centroidLat += (p1.lat + p2.lat) * f;
area += f;
}
area /= 2;
centroidLon /= (6 * area);
centroidLat /= (6 * area);
// 转换回笛卡尔坐标
return Cesium.Cartesian3.fromDegrees(centroidLon, centroidLat);
}
移除geojson数据
js
// 移除GeoJSON
viewer.dataSources.remove(lastAddedDataSource)