Cesium实现拖拽放大缩小实体圆功能
- 场景说明: 使用cesium绘制一个实体圆,需要在实体圆上标注一点,通过拖拽这个点实现对实体圆的放大缩小功能:
- 实现原理: 绘制一个实体圆,并绘制一个锚点,锚点的位置是通过圆形与半径计算出来的。
3: 关键代码:
第一步: 绘制实体圆:
假设圆心为center = {
longitude: 121,
latitude: 30
}
radius: 300 // 半径为300米
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
center.longitude,
center.latitude
),
name: 'rangeCircle',
id: 'rang001', // 实体圆的Id
ellipse: {
semiMinorAxis: radius,
semiMajorAxis: radius,
height: 400,
material: Cesium.Color.fromCssColorString('rgba(0, 0, 0, 0.3)'),
outline: true,
outlineColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 0.5)'),
outlineWidth: 3.0
}
})
第二歩: 绘制实体圆上的锚点:
// 判断锚点是否存在
const hasDrag = viewer.entities.getById('drag001')
// 根据圆心和半径计算锚点的经纬度
getDragPosition (center, radius) {
let dragPosition = null
const ellRadius = 6371 // 地球半径,单位千米
const distance = radius / 1000 // 将周边范围单位转化为千米
const dlng = 2 * Math.asin(Math.sin(distance / (2 * ellRadius)) / Math.cos(center.latitude * Math.PI / 180))
const dlat = distance / ellRadius
const parseLng = dlng * 180 / Math.PI
const parseLat = dlat * 180 / Math.PI
dragPosition = {
parseLng: parseLng,
parseLat: parseLat
}
return dragPosition
}
const dragPosition = getDragPosition(center, radius)
// 判断是否存在拖拽锚点
if (hasDrag) {
hasDrag.position = Cesium.Cartesian3.fromDegrees(
center.longitude + dragPosition.parseLng,
center.latitude,
400 // 高度
)
hasDrag.label.text = radius + '米'
} else {
viewer.entities.add({
id: 'drag001',
position: Cesium.Cartesian3.fromDegrees(
center.longitude + dragPosition.parseLng,
center.latitude,
400
),
billboard: {
image: require('@/images/ResponseModule/drag.svg'), // 锚点图片自己找就可以
show: true,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(8, 0)
},
label: {
text: `${radius}米`,
font: '16px',
fillColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 1)'),
outlineColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 1)'),
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
showBackground: true,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(50, 10)
}
})
}
第三步: 拖拽放大缩小实现
// 鼠标左键事件
leftDown () { this.downHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
this.downHandler.setInputAction((movement) => {
const picked = this.viewer.scene.pick(movement.position)
// 当鼠标左键点击拖拽点的时候
if (Cesium.defined(picked) && picked.id._id === 'drag001') {
this.viewer.scene.screenSpaceCameraController.enableRotate = false
this.zoom()
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
},
//
zoom () {
this.zoomHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
this.zoomHandler.setInputAction((movement) => {
// const ray = this.viewer.camera.getPickRay(movement.endPosition)
// const cartesian = this.viewer.scene.pickPosition(movement.endPosition)
const ray = this.viewer.camera.getPickRay(movement.endPosition)
const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene)
// const parseCartesian = MapConverData.cartesianToLng(cartesian)
this.positions.push(cartesian)
// 获取到拖动点的位置距离圆心的距离作为半径
this.radius = parseFloat(this.getSpaceDistance(this.positions))
const hasRange = this.viewer.entities.getById('rang001')
// 在鼠标移动的过程中不断更新拖拽点的位置
const dragPosition = getDragPosition(center, this.radius)
const hasDrag = this.viewer.entities.getById('drag001')
if (hasDrag) {
hasDrag.position = Cesium.Cartesian3.fromDegrees(
center.longitude + dragPosition.parseLng,
center.latitude,
400
)
hasDrag.label.text = this.radius + '米'
}
// 设置实体圆的半径
if (hasRange) {
hasRange.ellipse.semiMinorAxis = new Cesium.CallbackProperty(() => {
return this.radius
}, false)
hasRange.ellipse.semiMajorAxis = new Cesium.CallbackProperty(() => {
return this.radius
}, false)
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
},
// 右键点击完成标点
rightClick () {
const rightHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
rightHandler.setInputAction((movement) => {
// 设置鼠标默认样式
this.viewer._container.style.cursor = 'default'
this.viewer.scene.screenSpaceCameraController.enableRotate = true
// 销毁鼠标左键和鼠标move事件
this.zoomHandler = this.zoomHandler && this.zoomHandler.destroy(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
this.downHandler = this.downHandler && this.downHandler.destroy(Cesium.ScreenSpaceEventType.LEFT_DOWN)
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
},
// 只计算起点和终点的距离
getSpaceDistance (positions) {
var distance = 0
const start = _head(positions)
const end = _last(positions)
// for (var i = 0; i < positions.length - 1; i++) {
var point1cartographic = Cesium.Cartographic.fromCartesian(start)
var point2cartographic = Cesium.Cartographic.fromCartesian(end)
/** 根据经纬度计算出距离**/
var geodesic = new Cesium.EllipsoidGeodesic()
geodesic.setEndPoints(point1cartographic, point2cartographic)
var s = geodesic.surfaceDistance
// 返回两点之间的距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2))
distance = distance + s
// }
return Math.round(distance)
}