在进行cesium开发过程中,总是遇到要求对实体点线面进行编辑的需求,就写了一个通用的编辑方法,分享一下,大家在后续有相同需求的时候可以直接复用
使用方式就是直接引用js文件,然后通过editActive激活,editDeactive关闭就可以
import * as Cesium from "cesium";
var handler;
// 用于保存实体的对象
var gon;
// 设置当前的编辑点
let currentPoint;
// 判断是否处于编辑状态
let isEditting = false;
// 清空编辑点ID数组
let pointsId = [];
const editActive = (viewer) => {
handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
//取消之前的监听函数
handler.setInputAction(event => {
if (isEditting && currentPoint) {
// 获取屏幕坐标,移动监听与点击有所不同,所以有起始位置和终点位置
let windowPosition = event.endPosition;
// 将屏幕坐标转为笛卡尔坐标
let ellipsoid = viewer.scene.globe.ellipsoid;
let cartesian = viewer.camera.pickEllipsoid(windowPosition, ellipsoid);
// 如果点击到地球外,那么返回
if (!cartesian) {
return;
}
// 更新编辑点的位置
currentPoint.position = cartesian;
// 创建面标每个点位置信息的数组,并循环赋值
let points = [];
for (let id of pointsId) {
points.push(viewer.entities.getById(id).position._value);
}
if (gon.type == "polygon") {
// 更新面标的位置数组
gon.polygon.hierarchy = new Cesium.CallbackProperty(function () {
return new Cesium.PolygonHierarchy(points);
}, false);
gon.polyline.positions = new Cesium.CallbackProperty(function () {
return points.concat([points[0]]);
}, false);
} else if (gon.type == "polyline") {
gon.polyline.positions = new Cesium.CallbackProperty(function () {
return points;
}, false);
} else if (gon.type == "point") {
gon.position._value = cartesian;
} else if (gon.type == "circle") {
gon.position._value = cartesian;
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(event => {
var pick = viewer.scene.pick(event.position);
let pointList = [];
if (pick && pick.id !== gon && pick.id.name !== "editPointEntity") {
isEditting = false;
currentPoint = undefined;
// 移除编辑点,清空编辑点数组
for (let id of pointsId) {
viewer.entities.removeById(id);
}
pointsId = [];
editDeactive(viewer);
}
if (pick && pick.id && pick.id.name == "drawEntity" && !isEditting) {
gon = pick.id;
//判断要素为点线面类型
if (gon.type == "polygon") {
pointList = gon.polygon.hierarchy._value ? gon.polygon.hierarchy._value.positions : gon.polygon.hierarchy._callback().positions
} else if (gon.type == "polyline") {
pointList = gon.polyline.positions._value ? gon.polyline.positions._value.positions : gon.polyline.positions._callback()
} else if (gon.type == "point") {
pointList = [gon.position._value];
} else if (gon.type == "circle") {
pointList.push(gon.position._value);
}
pointList.forEach((item) => {
let point = viewer.entities.add({
name: "editPointEntity",
position: item,
type: item.type ? item.type : "",
point: {
color: Cesium.Color.SKYBLUE,
pixelSize: 10,
outlineColor: Cesium.Color.YELLOW,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
// 保存点的ID以便删除
pointsId.push(point.id);
});
// 设置编辑状态为true
isEditting = true;
// 禁止地球旋转和缩放,地球的旋转会对鼠标移动监听有影响,所以需要禁止
viewer.scene.screenSpaceCameraController.enableRotate = false;
viewer.scene.screenSpaceCameraController.enableZoom = false;
} else if (pick && pick.id && pick.id.name === "editPointEntity") {
currentPoint = pick.id;
viewer.scene.screenSpaceCameraController.enableRotate = false;
viewer.scene.screenSpaceCameraController.enableZoom = false;
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
handler.setInputAction(() => {
// 移除当前编辑点
currentPoint = undefined;
viewer.scene.screenSpaceCameraController.enableRotate = true;
viewer.scene.screenSpaceCameraController.enableZoom = true;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
// 点击右键事件
handler.setInputAction(() => {
editDeactive(viewer);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};
const editDeactive = (viewer) => {
if (isEditting) {
// 移除监听器
if (handler !== null && !handler.isDestroyed()) {
handler.destroy();
}
// 移除编辑点,清空编辑点数组
for (let id of pointsId) {
viewer.entities.removeById(id);
}
pointsId = [];
isEditting = false;
}
};
export default {
editActive,
editDeactive
};