前言
如果你是在寻求解决方案,可以直接用cesium-draw这个插件。
鼠标左键添加点、右键完成绘制,单击右侧弹窗关闭按钮清空绘制。参考沙盒示例:Drawing on Terrain
直接上代码了
/** @Date: 2023-07-12 18:47:18* @LastEditors: ReBeX 420659880@qq.com* @LastEditTime: 2023-09-12 15:13:19* @FilePath: \cesium-tyro-blog\src\utils\Entity\Draw\polygon.js* @Description: 绘制面*/
import { viewer } from '@/utils/createCesium.js' // 引入地图对象
import * as Cesium from 'cesium'export class PolygonDrawer {activePoint // 动态点constructor(callback) {if (!Cesium.Entity.supportsPolylinesOnTerrain(viewer.scene)) {window.alert('This browser does not support polylines on terrain.')}if (!PolygonDrawer.instance) { // 首次使用构造器实例this.callback = callback// 新建DataSource用来管理entitiesthis.nodeCollection = new Cesium.CustomDataSource('nodeEntityCollection')this.polygonCollection = new Cesium.CustomDataSource('polygonEntityCollection')viewer.dataSources.add(this.nodeCollection)viewer.dataSources.add(this.polygonCollection)this.addHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) // 新增点位的交互句柄this.finHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) // 完成点选的交互句柄this.moveHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) // 完成点选的交互句柄viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK) // 关闭左键双击事件PolygonDrawer.instance = this // 将this挂载到PolygonDrawer这个类的instance属性上}return PolygonDrawer.instance // 返回单例}// 开始绘制start() {this.activePoint = this.createCursorPoint({ x: 0, y: 0, z: 0 }) // 默认显示动态点this.activePoint.position.setValue(undefined) // 隐藏指针点const pointList = [] // 初始化当前的线坐标数组// 事件:新增点this.addHandler.setInputAction(event => {// 获取地形表面经纬度和高度const ray = viewer.camera.getPickRay(event.position || event.endPosition)const cartesian = viewer.scene.globe.pick(ray, viewer.scene)// // 获取椭球体表面的经纬度// const cartesian = viewer.camera.pickEllipsoid(event.position || event.endPosition, viewer.scene.globe.ellipsoid);if (Cesium.defined(cartesian)) {this.nodeCollection.entities.add(this.createNodePoint(cartesian)) // 添加节点// 绘制动态线:首次点击后触发if (pointList.length === 0) {pointList.push(cartesian) // 加入一个动态点}if (pointList.length === 2) {const dynamicPositions = new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(pointList), false)this.polygonCollection.entities.add(this.createNormalPolygon(dynamicPositions)) // 绘制线}pointList.push(cartesian)}}, Cesium.ScreenSpaceEventType.LEFT_CLICK)// 事件:鼠标移动this.moveHandler.setInputAction(event => {if (Cesium.defined(this.activePoint)) {// 获取地形表面经纬度和高度const ray = viewer.camera.getPickRay(event.endPosition || event.position)const cartesian = viewer.scene.globe.pick(ray, viewer.scene)// // 获取椭球体表面的经纬度// const cartesian = viewer.camera.pickEllipsoid(event.position || event.endPosition, viewer.scene.globe.ellipsoid);if (Cesium.defined(cartesian)) {this.activePoint.position.setValue(cartesian)if (pointList.length > 0) {pointList.pop()pointList.push(cartesian)}} else {this.activePoint.position.setValue(undefined) // 指针超出地球外了就隐藏指针点}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)// 事件:完成绘制this.finHandler.setInputAction(event => {if (pointList.length < 2) { // 一个节点都没添加alert('请至少选3个点')} else if (pointList.length < 3) { // 如果点击了1次alert('请至少选3个点')console.log('this.nodeCollection.entities: ', this.nodeCollection.entities)this.nodeCollection.entities.remove(this.nodeCollection.entities.values[this.nodeCollection.entities.values.length - 1])this.polygonCollection.entities.remove(this.polygonCollection.entities.values[this.polygonCollection.entities.values.length - 1])} else if (pointList.length < 4) { // 如果点击了2次alert('请至少选3个点')this.nodeCollection.entities.remove(this.nodeCollection.entities.values[this.nodeCollection.entities.values.length - 1])this.nodeCollection.entities.remove(this.nodeCollection.entities.values[this.nodeCollection.entities.values.length - 1])this.polygonCollection.entities.remove(this.polygonCollection.entities.values[this.polygonCollection.entities.values.length - 1])this.polygonCollection.entities.remove(this.polygonCollection.entities.values[this.polygonCollection.entities.values.length - 1])}pointList.pop()this.stop()this.start()}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)}// 结束绘制stop() {this.addHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)this.moveHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)this.finHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)viewer.entities.remove(this.activePoint) // 移除动态点this.callback && this.callback(this.polygonCollection) // 如果需要,就把线集合给回调函数}// 绘制:动态点createCursorPoint(cartesian, show) {const point = viewer.entities.add({position: cartesian,point: {pixelSize: 5, // 像素大小,默认: 1heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 表示相对于地形的位置color: Cesium.Color.SKYBLUE, // 默认: 白disableDepthTestDistance: Number.POSITIVE_INFINITY}})return point}// 绘制:节点createNodePoint(cartesian) {return new Cesium.Entity({position: cartesian,point: {pixelSize: 3, // 像素大小,默认: 1heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 表示相对于地形的位置color: Cesium.Color.BLUE, // 默认: 白disableDepthTestDistance: Number.POSITIVE_INFINITY}})}// 绘制:面createNormalPolygon(list) {return new Cesium.Entity({polygon: {hierarchy: list,clampToGround: true,material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7))}})}// 销毁:清空绘制与监听destroy() {this.stop()this.nodeCollection.entities.removeAll()this.polygonCollection.entities.removeAll()}
}
调用:
// 引入
import { PolygonDrawer } from '@/utils/Entity/Draw/polygon.js'// 声明实例:无回调函数
const polygonDrawer = new PolygonDrawer()// 声明实例:有回调函数
const polygonDrawer = new PolygonDrawer((lineList)=> {console.log(lineList)
);// 开始绘制
PolygonDrawer.start()// 结束绘制并清除所有点和线
PolygonDrawer.destroy()
最后
关联内容:【CesiumJS入门】(7)绘制多段线(动态实时画线)