前言:基于cesium实现画多边形以及对其编辑
效果:cesium绘制实时绘制多边形并编辑多边形_哔哩哔哩_bilibili
思路:
1.创建cesium (省略.....)
2.理清需要那些功能,在这里我们用到了cesium得画点,画线,画面,以及对鼠标得左键,右键,和移动得监听
3.接下来就开始创作了,其中还有一些细节,大家自行体会,
话不多说直接上代码
完整代码如下,当然还有一些缺陷或者bug,请大家指正,我会改进
// 画面点位数据
let pointArr = []
// 当前点位的数据
let nowPoint = []
// 当前多边形中的点和线实体集合
let pointAndLineEntity = {
pointEntityArr: [],
lineEntityArr: [],
demoLineEntityArr: [],
polygonEntityArr: []
}
// 当前选择的编辑点
let nowEditPoint = []
// 是否开始画多边形
let isDrawLine = false
// 是否形成面
let isDrawPolyGon = false
// 事件
const editPolyGonFunC = {
// 删除实体
// 删除鼠标移动生成的线
delDemoEntity: (name) => {
name == 'point_name' && pointAndLineEntity.pointEntityArr.forEach(item => {
viewer.entities.remove(item)
})
name == 'line_name' && pointAndLineEntity.lineEntityArr.forEach(item => {
viewer.entities.remove(item)
})
name == 'line_demo_name' && pointAndLineEntity.demoLineEntityArr.forEach(item => {
viewer.entities.remove(item)
})
},
// 画面
draw: () => {
// 经纬度转换
const getLonOrLat = (cartesian2) => {
var cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(cartesian2), viewer.scene);
// console.log('cartesian',cartesian);
let cartorgraphic = Cesium.Cartographic.fromCartesian(cartesian);
// console.log('ddd', cartorgraphic);
let lon = Cesium.Math.toDegrees(cartorgraphic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartorgraphic.latitude); // 纬度
// console.log(`经度:${lon},纬度:${lat}`);
return {
longitude: lon,
latitude: lat
}
}
// 画点
const drawPoint = (lonAndLat) => {
const entityPoint = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(lonAndLat[0], lonAndLat[1], lonAndLat[2]),
name: 'point_name',
point: {
color: Cesium.Color.fromCssColorString('#fc3d4a'),
outlineColor: Cesium.Color.fromCssColorString('#fc3d4a'),
pixelSize: 11
},
})
return entityPoint
}
// 画线
const drawLine = (name, lineArr) => {
const entityLine = viewer.entities.add({
name: name,
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(lineArr),
width: 5,
material: Cesium.Color.fromCssColorString('#fcc31f'),
}
})
return entityLine
}
// 画面
const drawPolyGon = (lonAndLat) => {
let lonLats = (data) => {
let arr = []
for (let d in data) {
//判断经纬度范围
if (
data[d][0] >= -180 &&
data[d][0] <= 180 &&
data[d][1] >= -90 &&
data[d][1] <= 90
) {
arr.push(data[d][0], data[d][1])
} else {
console.log('经纬度数值不对:', data[d][0], data[d][1])
}
}
return arr
}
viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(lonAndLat[0], lonAndLat[1], lonAndLat[2]),
name: "polyGon_name",
polygon: {
clampToGround: true, //开启贴地
hierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray(lonLats(lonAndLat))
),
material: Cesium.Color.BLUE.withAlpha(0.5),
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 300000)
}
});
}
// 声明监听事件
let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas)
// 监听鼠标左击事件
handler.setInputAction((event) => {
// console.log('ddd', event);
let pick = viewer.scene.pick(event.position)
// console.log('ddd pick', pick);
// 判断是否有实体
if (pick && pick.id && pick.id.polygon) {
if (!pointAndLineEntity.polygonEntityArr.includes(pick) && pointAndLineEntity.polygonEntityArr.length == 0) {
// 实体存在生成编辑点
for (let cartesian of pick.id.polygon.hierarchy._value.positions) {
const point = viewer.entities.add({
name: "polygon_point",
position: cartesian,
point: {
color: Cesium.Color.WHITE,
pixelSize: 8,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 1,
},
});
// 保存点的ID以便删除
pointAndLineEntity.pointEntityArr.push(point)
}
pointAndLineEntity.polygonEntityArr.push(pick)
} else {
console.log('已生成编辑点,或只能存在一个');
}
} else if (pick && pick.id && pick.id.point && (pick.id.name == 'polygon_point')) {
console.log('编辑点保存');
nowEditPoint = []
nowEditPoint.push(pick)
isDrawPolyGon = true
// console.log('ddd pointAndLineEntity', pointAndLineEntity);
// console.log('ddd nowEditPoint', nowEditPoint);
} else {
// 实体不存在开始画多边形
if (!isDrawPolyGon) {
// 获取坐标信息
let nowPosition = getLonOrLat(event.position)
// 点数据保存
pointArr.push([nowPosition.longitude, nowPosition.latitude, 0])
// console.log('pointArr', pointArr);
// 当前点数据
nowPoint = [nowPosition.longitude, nowPosition.latitude, 0]
// 画点
const point = drawPoint([nowPosition.longitude, nowPosition.latitude, 0])
pointAndLineEntity.pointEntityArr.push(point)
// 开始画多边形
isDrawLine = true
// 画线
const num = pointArr.length
if (num > 1) {
editPolyGonFunC.delDemoEntity('line_demo_name')
const line = drawLine('line_name', [...pointArr[num - 2], ...pointArr[num - 1]])
pointAndLineEntity.lineEntityArr.push(line)
}
} else {
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
// 鼠标移动事件
handler.setInputAction((event) => {
if (isDrawLine && !isDrawPolyGon) {
// 画框逻辑
// -------
// console.log('ddd event', event);
// 获取坐标信息
let movePosition = getLonOrLat(event.startPosition)
// console.log('ddd nowPosition', movePosition);
// 删除上一次生成
editPolyGonFunC.delDemoEntity('line_demo_name')
// 创建线
const demoLine = drawLine('line_demo_name', [...nowPoint, ...[movePosition.longitude, movePosition.latitude, 0]])
pointAndLineEntity.demoLineEntityArr.push(demoLine)
} else if (isDrawPolyGon && !isDrawLine) {
// 编辑逻辑
// -------
// 获取坐标信息
let movePosition = getLonOrLat(event.startPosition)
// 更新点坐标
nowEditPoint[0].id.position = Cesium.Cartesian3.fromDegrees(movePosition.longitude, movePosition.latitude, 0)
// 获取更新面坐标的数据
let points = [];
pointAndLineEntity.pointEntityArr.forEach(item => {
points.push(item.position._value);
})
// console.log('points',points);
// 更新面坐标
pointAndLineEntity.polygonEntityArr[0].id.polygon.hierarchy = points;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
// 鼠标右击事件
handler.setInputAction((event) => {
// console.log('ddd event', event);
if (!isDrawPolyGon && isDrawLine) {
// 结束画多边形
isDrawLine = false
// 删除鼠标移动画线
editPolyGonFunC.delDemoEntity('line_demo_name')
// 封闭多边形
// const num = pointArr.length
// drawLine('line_name', [...pointArr[num - 1], ...pointArr[0]])
// 画多边形结束,形成面开始
drawPolyGon(pointArr)
// 清空数据
// 删除画点以及画线
editPolyGonFunC.delDemoEntity('line_name')
editPolyGonFunC.delDemoEntity('point_name')
pointArr = []
nowPoint = []
pointAndLineEntity = {
pointEntityArr: [],
lineEntityArr: [],
demoLineEntityArr: [],
polygonEntityArr: []
}
// console.log('ddd', viewer.entities);
// console.log('ddd', viewer);
// isDrawPolyGon = true
} else if (isDrawPolyGon && !isDrawLine) {
isDrawPolyGon = false
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
},
// 重置
klk: () => {
editPolyGonFunC.delDemoEntity('point_name')
isDrawLine = false
isDrawPolyGon = false
pointAndLineEntity = {
pointEntityArr: [],
lineEntityArr: [],
demoLineEntityArr: [],
polygonEntityArr: []
}
nowEditPoint = []
}
}
最后谢谢大家观看,第一次创作,感谢大家!
如有不好的地方,欢迎指正.
也作为在工作当中的积累,展示在这里.