刚刚分享了地形开挖,觉得可能大部分业务是自定义多边形,然后开挖,基于此,分享自定义绘制多边形函数,引入即可使用
// 构造唯一id
import { v4 as uuidv4 } from 'uuid';
// 坐标转化
const getLonLatFromCartesian = (cartesian3) => {
const { longitude, latitude, height } = Cesium.Cartographic.fromCartesian(cartesian3);
return {
lng: +Cesium.Math.toDegrees(longitude),
lat: +Cesium.Math.toDegrees(latitude),
height: +height
}
};
// 创建点
const createPoint = (viewer, Cartesian, options) => {
const { lng, lat, height } = getLonLatFromCartesian(Cartesian)
return viewer.entities.add({
position: new Cesium.Cartesian3.fromDegrees(lng, lat, height),
point: {
pixelSize: options.pixelSize,
color: options.pointColor
}
})
};
// 绘制多边形
const DrawPolygon = (viewer, options = {}, callback) => {
if (!viewer) throw new Error("no viewer object!");
options = {
id: uuidv4(),
pointColor: Cesium.Color.fromCssColorString('#FFC107'),
pixelSize: 8,
outlineWidth: 5,
outlineColor: new Cesium.Color(0, 64 / 255, 133 / 255, 0.8),
color: Cesium.Color.fromCssColorString('rgba(0, 123, 255, 0.4)'),
...options
};
if (viewer.entities.getById(options.id)) {
throw new Error("the id is an unique value");
}
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
let activeShapePoints = [];
let polygon = undefined;
let floatingPoint = undefined;
// 鼠标左击事件
handler.setInputAction((event) => {
let ray = viewer.camera.getPickRay(event.position);
let earthPosition = viewer.scene.globe.pick(ray, viewer.scene);
// 鼠标开始点击多边形的第一个点
if (activeShapePoints.length === 0) {
floatingPoint = createPoint(viewer, earthPosition, options);
// 将第一个左击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition);
// 多边形的坐标采用回调的形式
// 多边形边界顶点
let polylinePoints = new Cesium.CallbackProperty(() => {
let vertexPoints = activeShapePoints.concat([activeShapePoints[0]]);
return vertexPoints;
}, false);
// 多边形顶点
let dynamicPositions = new Cesium.CallbackProperty(() => {
return new Cesium.PolygonHierarchy(activeShapePoints);
}, false);
// 添加一个多边形
polygon = viewer.entities.add({
name: "customPolygon",
id: options.id,
polyline: {
positions: polylinePoints,
width: options.outlineWidth,
material: options.outlineColor,
clampToGround: true,
},
polygon: {
hierarchy: dynamicPositions,
material: options.color,
heightReference: Cesium.HeightReference.NONE,
},
});
}
// 将鼠标点击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition);
// 记录多边形边界的点
polygon.outLinePoint = (polygon.outLinePoint ?? []).concat(createPoint(viewer, earthPosition, options));
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 鼠标移动事件
handler.setInputAction((movement) => {
// 获取鼠标所在的位置
const ray = viewer.camera.getPickRay(movement.endPosition);
const newPosition = viewer.scene.globe.pick(ray, viewer.scene);
// 已经定义了polygon
if (Cesium.defined(polygon)) {
floatingPoint.position.setValue(newPosition);
// 删除多边形顶点中最新的一个点
activeShapePoints.pop();
// 将最新获取到的点添加到多边形顶点集合中
activeShapePoints.push(newPosition);
}
if (activeShapePoints.length === 3) {
polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(() => {
// 删除最后一个点(重复添加的点)
activeShapePoints.pop();
polygon.pottingPoint = activeShapePoints;
viewer.entities.remove(floatingPoint);
floatingPoint = undefined;
// 销毁右击事件
handler.destroy();
if (typeof callback === "function") callback(polygon);
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
};
export default DrawPolygon;
使用方法
DrawPolygon(this.viewer, {}, (polygon) => {
console.log(polygon)
})