一般在gis开发中,像Openlayers, Leaflet等二维地图库,都提供测距的功能。但是在Cesium三维地图库中,支持测距,测面和测高。
实现一个如下图的测距功能
💡实现思路
- 在地图上绘制点与线;2. 计算点与点之间距离, 每条段线添加长度提示标签;3. 起点与终点添加标识
一.绘制点
绘制点分为两类:一类为起始点和终点,是需要添加图标的,一类是普通的添加点
// 创建排除起点/终点的点
private createVertex() {
let vertexEntity = this.options.viewer.entities.add({
position: this.positions[this.positions.length - 1],
id: 'MeasureDistanceVertex' + this.positions[this.positions.length - 1],
type: 'MeasureDistanceVertex',
label: {
text: this.spaceDistance(this.positions) + '米',
scale: 0.5,
font: 'normal 24px MicroSoft YaHei',
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: new Cesium.Cartesian2(0, -30),
outlineWidth: 9,
outlineColor: Cesium.Color.WHITE
},
point: {
color: Cesium.Color.FUCHSIA,
pixelSize: 8,
disableDepthTestDistance: 500
}
})
this.vertexEntities.push(vertexEntity)
}
// 创建起点实体
private createStartEntity() {
let vertexEntity = this.options.viewer.entities.add({
position: this.positions[0],
type: 'MeasureDistanceVertex',
billboard: {
image: startPoint,
width: 36,
height: 36,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: Number.POSITIVE_INFINITY
},
point: {
color: Cesium.Color.FUCHSIA,
pixelSize: 6
}
})
this.vertexEntities.push(vertexEntity)
}
二.绘制线
private createLineEntity() {
this.lineEntities = viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty((e: Event) => {
return this.tempPositions
}, false),
width: 2,
material: this.options.lineColor,
depthFailMaterial: this.options.lineColor,
disableDepthTestDistance: 500,
clampToGround: true
}
})
}
三.计算点与点之间距离
private spaceDistance(positions: IPosition[]) {
let distance = 0
for (let i = 0; i < positions.length - 1; i++) {
let point1cartographic = Cesium.Cartographic.fromCartesian(positions[i])
let point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1])
// 根据经纬度计算出距离
let geodesic = new Cesium.EllipsoidGeodesic()
geodesic.setEndPoints(point1cartographic, point2cartographic)
let s = geodesic.surfaceDistance
// 返回两点之间的距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2))
distance = distance + s
}
return distance.toFixed(2)
}
四.Cesium中鼠标事件的注册
在添加完绘制的所有事件后,需要注册Cesium中的鼠标点击事件,鼠标右键结束绘制事件,以及记录鼠标移动过程中移动事件。
this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
this.handler.setInputAction((e: any) => {
// 点的创建的相关处理
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
this.handler.setInputAction((e: any) => {
// 绘制结束的相关处理
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
this.handler.setInputAction((e: any) => {
// 鼠标移动过程中,点的相关记录
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
五.Cesium中鼠标事件的移除
private unRegisterEvents() {
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}