思路和之前做 Cesium 点击绘制多边形(动态绘制多边形)
一样的,点击查看
这里重点说一下: CallbackProperty
是一个类,其值由回调函数延迟计算。也就是说它在不断地自我调用,每当其返回的对象有改变时,就会抛出改变后的值。利用这种特性,我们就可以在定义positions
时,用CallbackProperty生成动态的数组赋值给positions
参数,就可以得到动态绘制线/折线的效果。
使用方法:调用 click_draw_polygon() 方法就可以
// 保存所有点的数据
var polyline_point_arr = [];
// 临时线entity
var temporary_polyline_entity = null;
var handler = null;
// 开启绘制的方法
function click_draw_polyline() {
// 清除可能会用到的监听事件
if (handler) {
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
//鼠标左键--确定选中点
handler.setInputAction((event) => {
// 屏幕坐标转为世界坐标
let cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(event.position), viewer.scene);
let ellipsoid = viewer.scene.globe.ellipsoid;
let cartographic = ellipsoid.cartesianToCartographic(cartesian);
let lat = Cesium.Math.toDegrees(cartographic.latitude);
let lon = Cesium.Math.toDegrees(cartographic.longitude);
// 判断是否定义(是否可以获取到空间坐标)
if (Cesium.defined(cartesian)) {
// 将点添加进保存线的坐标的数组中,鼠标停止移动的时添加的点和,点击时候添加的点,坐标一样
// 注意顺序不能错了,先经度后纬度
polyline_point_arr.push(lon);
polyline_point_arr.push(lat);
// 判断是否开始绘制动态线,没有的话则开始绘制
if (temporary_polyline_entity == null) {
// 绘制动态线
draw_dynamic_polyline();
}
}
//鼠标移动--实时绘制线
handler.setInputAction((event) => {
// 屏幕坐标转为世界坐标
let cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(event.endPosition), viewer.scene);
let ellipsoid = viewer.scene.globe.ellipsoid;
let cartographic = ellipsoid.cartesianToCartographic(cartesian);
let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
// 判断是否定义(是否可以获取到空间坐标)
if (Cesium.defined(cartesian)) {
// 判断是否已经开始绘制动态线,已经开始的话,则可以动态拾取鼠标移动的点,修改点的坐标
if (temporary_polyline_entity) {
// 只要元素点大于二,每次就删除二个点,因为实时动态的点是添加上去的
if (polyline_point_arr.length > 2) {
// 删除数组最后两个元素(鼠标移动添加进去的点)
polyline_point_arr.pop();
polyline_point_arr.pop();
}
// 将新的点添加进动态线的坐标的数组中,用于实时变化,注意:这里是先添加了一个点,然后再删除点,再添加,这样重复的
// 注意顺序不能错了,先经度后纬度
polyline_point_arr.push(lon);
polyline_point_arr.push(lat);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标右键--结束绘制
handler.setInputAction((event) => {
// 取消鼠标移动监听
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 清除动态绘制的线
viewer.entities.remove(temporary_polyline_entity);
// 删除保存的临时线的entity
temporary_polyline_entity = null;
// 绘制结果线
draw_polyline();
// 清空线点数组,用于下次绘制
polyline_point_arr = [];
// 清除所有事件
if (handler) {
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//绘制动态线
function draw_dynamic_polyline() {
temporary_polyline_entity = viewer.entities.add({
polyline: {
// 这个方法上面有重点说明
positions: new Cesium.CallbackProperty(() => {
return new Cesium.Cartesian3.fromDegreesArray(polyline_point_arr);
}, false),
// 宽度
width: 2,
// 线的颜色
material: Cesium.Color.RED,
// 是否显示
show: true
}
});
}
//绘制结果线
function draw_polyline() {
// 不需要线条闭合的话,删除最后一个动态添加的点(经度和纬度),如果鼠标没移动,最后一个和倒数第二个是一样的,所以也要删除
polyline_point_arr.pop();
polyline_point_arr.pop();
// 需要线条闭合的话,下面两句(将起始点添加到结尾)
// polyline_point_arr[polyline_point_arr.length - 2] = polyline_point_arr[0];
// polyline_point_arr[polyline_point_arr.length - 1] = polyline_point_arr[1];
// 两个点以上才能绘制成线
if (polyline_point_arr.length >= 2) {
let polyline_point_entity = viewer.entities.add({
polyline: {
// Cesium.Cartesian3.fromDegreesArray([经度1, 纬度1, 经度2, 纬度2,])
// Cesium.Cartesian3.fromDegreesArrayHeights([经度1, 纬度1, 高度1, 经度2, 纬度2, 高度2])
// 如果有高度,上面的 polyline_point_arr 里面要增加高度的
positions: new Cesium.Cartesian3.fromDegreesArray(polyline_point_arr),
// 宽度
width: 2,
// 线的颜色
material: Cesium.Color.RED,
// 是否显示
show: true
}
});
} else {
return
}
}