【CesiumJS入门】(10)绘制多边形(动态实时画面)

前言

如果你是在寻求解决方案,可以直接用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用来管理entities
      this.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, // 像素大小,默认: 1
        heightReference: 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, // 像素大小,默认: 1
        heightReference: 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)绘制多段线(动态实时画线)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值