当前位置: 首页 > news >正文

基于 Cesium.js 的交互式绘图工具库

这是一个基于 Cesium.js 的交互式绘图工具库,包含两个主要类:PositionTransfer(坐标转换工具)和 DrawTool(绘图工具)。


1. PositionTransfer 类

功能:处理不同坐标系统间的转换,如经纬度、笛卡尔坐标、屏幕坐标等。

主要方法:
  • cartesian3ToLng(position)
    将 Cesium.Cartesian3(三维笛卡尔坐标)转换为经纬度和高度(WGS84 坐标系)。

  • lngToCartesian3(position)
    将经纬度对象 {lng, lat, height} 转换为 Cesium.Cartesian3

  • screenPositionToCartesian3(position)
    将屏幕坐标(Cesium.Cartesian2)转换为世界坐标(Cesium.Cartesian3),考虑地形和 3D 模型。

  • generateCirclePoints(center, radius)
    根据圆心和半径生成圆形边缘的经纬度点集合,用于绘制圆形。


2. DrawTool 类

功能:实现交互式绘制点、线、多边形、矩形、圆等几何图形,支持贴地或固定高度模式。

核心特性:
  • 绘制模式

    • ClampToGround: 图形贴附地形或 3D 模型表面。

    • None: 固定高度(默认)。

  • 支持的图形类型

    • 点(Point)、折线(Polyline)、多边形(Polygon)、矩形(Rect)、圆(Circle)。

  • 交互逻辑

    • 左键单击:添加点或调整图形形状。

    • 右键单击:结束绘制。

    • 鼠标移动:实时预览未完成的图形。

关键方法:
  • active(drawType)
    激活指定绘图类型,初始化事件监听和临时实体。

  • 生成图形方法

    • generatePolyline(): 动态更新折线顶点。

    • generateRect(): 通过两点计算矩形四个角点。

    • generateCircle(): 根据圆心和半径生成圆。

    • generatePolygon(): 多边形自动闭合。

  • 坐标拾取
    getcartesian3FromScreen(px) 处理从屏幕坐标到世界坐标的转换,兼容地形和 3D 模型。

  • 贴地处理
    setClamp() 根据模式设置图形是否贴地,利用 ClassificationType 实现。

  • 事件触发
    绘制结束时触发 DrawEndEvent,传递实体对象、坐标数据及图形类型。


3.使用示例

// 初始化 Viewer
const viewer = new Cesium.Viewer("cesiumContainer");

// 创建绘图工具实例
const drawTool = new DrawTool(viewer, { drawMode: "clampToGround" });

// 监听绘制完成事件
drawTool.DrawEndEvent.addEventListener((entity, positions, type, circlePoints) => {
  console.log("绘制完成:", type, positions);
});

// 激活多边形绘制
drawTool.active(drawTool.DrawTypes.Polygon);

4.代码亮点

  • 坐标系统无缝转换:支持复杂场景下的坐标精准拾取。

  • 动态预览:利用 CallbackProperty 实现图形实时更新。

  • 地形适配:通过 ClassificationType 确保图形贴合地形或模型表面。

  • 事件驱动设计:便于扩展和集成到其他功能模块。


5.潜在改进

  • 圆形精度:当前 getCirclePoint 假设地球为完美球体,可能在高纬度或大范围时产生误差,需改用测地线算法。

  • 撤销/重做:可添加历史记录功能,支持操作回退。

  • UI 交互:增强绘制提示(如文字标签、撤销按钮)。

此工具适用于需要在地球表面交互式绘制标绘物的场景,如地理标注、测量、规划等。

6.具体实现 

   PositionTransfer.js

import * as Cesium from "cesium";

class PositionTransfer {
  /**
   * 坐标转换工具
   * @param {Cesium.Viewer} viewer : viewer程序对象
   */
  constructor(viewer) {
    this.viewer = viewer;
  }

  /**
   * 笛卡尔转经纬度
   * @param {Cesium.Cartesian3} position : 笛卡尔三阶坐标
   */
  cartesian3ToLng(position) {
    // 获取当前椭球的坐标系统,其中包含了坐标转换工具
    const ellipsoid = this.viewer.scene.globe.ellipsoid;
    // 笛卡尔坐标转为弧度坐标
    const cartoGraphic = ellipsoid.cartesianToCartographic(position);
    // 将弧度坐标转为经纬度
    const lng = Cesium.Math.toDegrees(cartoGraphic.longitude);
    const lat = Cesium.Math.toDegrees(cartoGraphic.latitude);
    const height = cartoGraphic.height;
    return {
      lng,
      lat,
      height,
    };
  }

  /**
   * 笛卡尔转经纬度(方式2)
   * @param {Cesium.Cartesian3} position : 笛卡尔三阶坐标
   */
  cartesian3ToDegreesHeight(position) {
    let c = Cesium.Cartographic.fromCartesian(position);
    return [
      Cesium.Math.toDegrees(c.longitude),
      Cesium.Math.toDegrees(c.latitude),
      c.height,
    ];
  }

  /**
   * 根据笛卡尔获取位置高度
   * @param {Cesium.Cartesian3} position : 笛卡尔三阶坐标
   */
  getPositionHeight(position) {
    const cartographic = Cesium.Cartographic.fromCartesian(position);
    return cartographic.height;
  }

  getCirclePoint(lon, lat, angle, radius) {
    let dx = radius * Math.sin((angle * Math.PI) / 180.0);
    let dy = radius * Math.cos((angle * Math.PI) / 180.0);
    let ec = 6356725 + ((6378137 - 6356725) * (90.0 - lat)) / 90.0;
    let ed = ec * Math.cos((lat * Math.PI) / 180);
    let newLon = ((dx / ed + (lon * Math.PI) / 180.0) * 180.0) / Math.PI;
    let newLat = ((dy / ec + (lat * Math.PI) / 180.0) * 180.0) / Math.PI;
    return [newLon, newLat];
  }

  /**
   * 获取圆的边缘坐标
   * @param {Cesium.Cartesian3} center : 笛卡尔三阶坐标
   * @param {Number} radius : 半径
   */
  generateCirclePoints(center, radius) {
    let points = [];
    for (let i = 0; i < 360; i += 2) {
      points.push(this.getCirclePoint(center[0], center[1], i, radius));
    }
    return points;
  }

  /**
   * 经纬度转笛卡尔
   * @param {Object} position : 经纬度 {lng,lat,height}
   */
  lngToCartesian3(position) {
    const { lng, lat, height } = position;
    return new Cesium.Cartesian3.fromDegrees(lng, lat, height);
  }

  /**
   * 经纬度转笛卡尔(批量)
   * @param {Array<{lng,lat,height}>|Array<{lng,lat}>} positions : 经纬度坐标数组
   * @param {Boolean} isHeight 是否包含了高度
   */
  lngPositionsToCartesian3(positions, isHeight = false) {
    const resArr = [];
    if (Array.isArray(positions)) {
      positions.forEach((position) => {
        const { lng, lat, height } = position;
        if (isHeight) {
          resArr.push(lng, lat, height);
        } else {
          resArr.push(lng, lat);
        }
      });
      // 根据是否带高度,返回对应的数据
      return isHeight
        ? new Cesium.Cartesian3.fromDegreesArrayHeights(resArr)
        : new Cesium.Cartesian3.fromDegreesArray(resArr);
    }
  }

  /**
   * 屏幕坐标和笛卡尔坐标转换
   * @param {Cesium.Cartesian2} position : 屏幕坐标,笛卡尔2阶数据
   */
  screenPositionToCartesian3(position) {
    return this.viewer.scene.globe.pick(
      this.viewer.camera.getPickRay(position),
      this.viewer.scene
    );
  }

  /**
   * 世界坐标转屏幕坐标
   * @param {Cesium.Cartesian3} position : 世界坐标
   */
  cartesian3ToScreenPosition(position) {
    return Cesium.SceneTransforms.wgs84ToWindowCoordinates(
      this.viewer.scene,
      position
    );
  }

  // todo:世界坐标转为带地形高度的经纬度
}

export default PositionTransfer;

  DrawTool.js

import * as Cesium from "cesium";
import PositionTransfer from "./PositionTrans";

class DrawTool {
  /**
   * 绘制工具
   * @param {Cesium.Viewer} viewer : viewer程序对象
   */
  constructor(viewer, options = {}) {
    this.viewer = viewer;
    // 开启深度检测
    //this.viewer.scene.globe.depthTestAgainstTerrain = true;
    viewer.scene.globe.depthTestAgainstTerrain = true;

    // 设置线性深度
    // viewer.scene.logarithmicDepthBuffer = false;  // 禁用对数深度缓冲
    // viewer.scene.globe.linearDepth = true;        // 启用线性深度
    this.positionTool=new PositionTransfer(viewer)
    // 默认按照贴地模式绘制图元
    this.drawMode = Cesium.defaultValue(options.drawMode, this.DrawModes.ClampToGround);
    // 初始化handler,events
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.DrawEndEvent = new Cesium.Event(); //结束绘制事件
  }

  // 绘制模式,支持贴地和固定高度
  DrawModes = {
    ClampToGround: "clampToGround",
    None: "none",
  };

  DrawTypes = {
    Polyline: "Polyline",
    Rect: "Rect",
    Point: "Point",
    Circle: "Circle",
    Polygon: "Polygon",
  };

  // 激活工具,传入DrawType
  active(drawType) {
    // 如果在我们的绘制工具集合中,存在这个工具
    if (Object.keys(this.DrawTypes).includes(drawType)) {
      this.drawType = drawType;
      // 最终的坐标
      this.positions = [];
      // 绘制过程中的坐标
      this.curPositions = [];
      //   每次点击有一个标点,需要存储实体
      this.points = [];
      // 注册鼠标事件
      this.registerEvents();

      //设置鼠标状态
      this.viewer.enableCursorStyle = false;
      this.viewer._element.style.cursor = "default";
      this.createMarker(drawType);
    } else {
      return;
    }
  }

  createMarker(drawType) {
    this.marker = document.createElement("div");
    this.marker.innerHTML = `左键点击绘制${drawType},右键结束绘制`;
    this.marker.className = "marker-draw";
    this.viewer.cesiumWidget.container.appendChild(this.marker);
  }

  destoryMarker() {
    this.marker && this.viewer.cesiumWidget.container.removeChild(this.marker);
    this.marker = null;
  }

  registerEvents() {
    // 分别注册左键画点,右键结束画点,鼠标移动事件
    this.leftClickEvent();
    this.rightClickEvent();
    this.mouseMoveEvent();
  }

  /**
   * 屏幕坐标转笛卡尔,分别从模型,地形,地球表面进行讨论
   *
   * @param {Cesium.Cartesian2} px 屏幕坐标
   *
   * @return {Cesium.Cartesian3} Cartesian3 三维坐标
   */
  getcartesian3FromScreen(px) {
    if (this.viewer && px) {
      // 使用pick获取当前射线穿透的第一个物体
      const pick = this.viewer.scene.pick(px);
      let isOn3dtiles = false;
      let isOnTerrain = false;
      // 最终得到的笛卡尔坐标
      let cartesianRes = null;
      if (pick && pick.primitive.isCesium3DTileset) {
        isOn3dtiles = true;
      }
      // 判断是否加载了地形
      let boolTerrain =
        this.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
      // 如果没有点击到模型,并且加载了地形的话,走地形碰撞逻辑
      if (!isOn3dtiles && !boolTerrain) {
        const ray = this.viewer.scene.camera.getPickRay(px);
        if (!ray) return null;
        cartesianRes = this.viewer.scene.globe.pick(ray, this.viewer.scene);
        isOnTerrain = true;
      }
      // 如果没有加载地形,也没有3dtiles,就是拾取到地球上的坐标
      if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
        cartesianRes = this.viewer.scene.camera.pickEllipsoid(
          px,
          this.viewer.scene.globe.ellipsoid
        );
      }
      // 3dtiles
      if (isOn3dtiles) {
        cartesianRes = this.viewer.scene.pickPosition(px);
      }

      // 如果有笛卡尔坐标,避免笛卡尔坐标的高度小于0
      if (cartesianRes) {
        let position = this.positionTool.cartesian3ToDegreesHeight(cartesianRes);
        // 可以将坐标高度设置为>=0
        // if(position[2]<0){

        // }
        return cartesianRes;
      }
      return false;
    }
  }

  leftClickEvent() {
    // 单机鼠标左键画点
    this.handler.setInputAction((e) => {
      // 屏幕坐标转为笛卡尔坐标,分三种情况
      let position = this.getcartesian3FromScreen(e.position);
      if (!position) return;
      this.positions.push(position);
      this.curPositions.push(position);
      // 如果是第一个点,就开始根据drawType,绘制图案
      if (this.positions.length === 1) {
        this.startDraw();
        this.setClamp()
      }
      //  如果是画线或者画点,每次点击左键,都在同一位置画一个点,绘制线的端点
      if (
        this.drawType === this.DrawTypes.Polyline ||
        this.drawType === this.DrawTypes.Point
      ) {
        this.generatePoint(position);
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  }

  //   鼠标移动事件
  mouseMoveEvent() {
    this.handler.setInputAction((e) => {
      this.marker.style.left = e.endPosition.x + 20 + "px";
      this.marker.style.top = e.endPosition.y - 20 + "px";
      this.viewer._element.style.cursor = "default"; //由于鼠标移动时 Cesium会默认将鼠标样式修改为手柄 所以移动时手动设置回来
      let position = this.getcartesian3FromScreen(e.endPosition);
      if (!position || !this.drawEntity) return;
      // tempPositions是每次鼠标移动时,我们得到的坐标,this.position是我们左键点击才能得到的坐标
      this.curPositions = [...this.positions, position];
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }

  //   右键点击,结束绘制
  rightClickEvent() {
    this.handler.setInputAction(() => {
      // 如果还没有开始绘制,直接结束绘制状态
      if (!this.drawEntity) {
        this.deactive();
        return;
      }
      // 如果当前的坐标数量少于最小数量,直接结束
      if (this.positions.length < this.minPositionCount) {
        this.deactive();
        return;
      }
      // 根据各种绘制类型,要重新给坐标赋值,吧callback变为constant
      switch (this.drawType) {
        case this.DrawTypes.Polyline:
          this.drawEntity.polyline.positions = this.positions;
          break;
        case this.DrawTypes.Rect:
          this.drawEntity.polygon.hierarchy = new Cesium.PolygonHierarchy(
            this.getRectFourPoints()
          );
          this.drawEntity.polyline.positions = this.getRectFourPoints();
          this.positions = this.getRectFourPoints();
          this.positions.pop();
          break;
        case this.DrawTypes.Circle:
          this.drawEntity.ellipse.semiMinorAxis = this.getAxis();
          this.drawEntity.ellipse.semiMajorAxis = this.getAxis();
          this.minPositionCount = 2;
          break;
        case this.DrawTypes.Polygon:
          this.drawEntity.polygon.hierarchy = new Cesium.PolygonHierarchy(
            this.positions.concat(this.positions[0])
          );
          this.drawEntity.polyline.positions = this.positions.concat(
            this.positions[0]
          );
          break;
        default:
          break;
      }
      this.deactive();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  startDraw() {
    switch (this.drawType) {
      case this.DrawTypes.Point:
        // 对于点,直接结束绘制就完事了
        this.drawEntity = this.generatePoint(this.positions[0]);
        // 记录最小构成几何体的坐标数量,point:1,polyline:2,rect:2,circle:2,polygon:3
        this.minPositionCount = 1;
        break;
      case this.DrawTypes.Polyline:
        this.generatePolyline();
        this.minPositionCount = 2;
        break;
      case this.DrawTypes.Rect:
        this.generateRect();
        this.minPositionCount = 2;
        break;
      case this.DrawTypes.Circle:
        this.generateCircle();
        this.minPositionCount = 2;
        break;
      case this.DrawTypes.Polygon:
        this.generatePolygon();
        this.minPositionCount = 3;
      default:
        break;
    }
  }
  // 绘制点
  generatePoint(position) {
    const cartographic = Cesium.Cartographic.fromCartesian(position);
    const point = this.viewer.entities.add({
      Type: this.DrawTypes.Point,
      position: position,
      point: {
        pixelSize: 14,
        color: Cesium.Color.RED,
      },
    });
    this.points.push(point);
    return point;
  }

  //   绘制线,position使用callbackProperty
  generatePolyline() {
    this.drawEntity = this.viewer.entities.add({
      Type: this.DrawTypes.Polyline,
      polyline: {
        positions: new Cesium.CallbackProperty((e) => {
          return this.curPositions;
        }, false),
        width: 2,
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.YELLOW,
        })
      },
    });
  }

  //   绘制矩形,由polygon和polyline组成
  generateRect() {
    this.drawEntity = this.viewer.entities.add({
      Type: this.DrawTypes.Rect,
      polygon: {
        hierarchy: new Cesium.CallbackProperty((e) => {
          return new Cesium.PolygonHierarchy(this.getRectFourPoints());
        }, false),
        material: Cesium.Color.RED.withAlpha(0.6)
      },
      polyline: {
        positions: new Cesium.CallbackProperty((e) => {
          return this.getRectFourPoints();
        }, false),
        width: 1,
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.YELLOW,
        }),
        depthFailMaterial: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.YELLOW,
        })
      },
    });
  }

  setClamp() {
    // 设置贴地
    if (this.drawMode === "clampToGround") {
      if(this.drawEntity.ellipse){
        this.drawEntity.ellipse.classificationType =
        Cesium.ClassificationType.BOTH;
      }
      if(this.drawEntity.polygon){
        this.drawEntity.polygon.classificationType =Cesium.ClassificationType.BOTH;
        this.drawEntity.polygon.perPositionHeight=false
      }
      if(this.drawEntity.polyline){
        this.drawEntity.polyline.classificationType =
          Cesium.ClassificationType.BOTH;
        this.drawEntity.polyline.clampToGround = true;
      }
    } else {
      if(this.drawEntity.ellipse){
        this.drawEntity.ellipse.height = this.positionTool.getPositionHeight(this.positions[0]);
      }
      if(this.drawEntity.polygon){
        this.drawEntity.polygon.classificationType = undefined
        this.drawEntity.polygon.perPositionHeight=true
      }
      if(this.drawEntity.polyline){
        this.drawEntity.polyline.classificationType = undefined;
        this.drawEntity.polyline.clampToGround = false;
      }
    }
  }

  // 获取矩形四个点
  getRectFourPoints() {
    let res = this.curPositions;
    if (this.curPositions.length > 1) {
      let p1 = this.curPositions[0];
      let p2 = this.curPositions[1];

      let c1 = Cesium.Cartographic.fromCartesian(p1);
      let c2 = Cesium.Cartographic.fromCartesian(p2);
      if (c1.height < 0) c1.height = 0;
      if (c2.height < 0) c2.height = 0;
      let lls = this.getRectanglePointsByTwoPoint(c1, c2);

      // 坐标数组转为指定格式
      let ars = [
        lls[0][0],
        lls[0][1],
        c1.height,
        lls[1][0],
        lls[1][1],
        c1.height,
        lls[2][0],
        lls[2][1],
        c1.height,
        lls[3][0],
        lls[3][1],
        c1.height,
        lls[0][0],
        lls[0][1],
        c1.height,
      ];
      res = Cesium.Cartesian3.fromDegreesArrayHeights(ars);
    }
    return res;
  }

  //   获取矩形四个点
  getRectanglePointsByTwoPoint(c1, c2) {
    //转为经纬度
    let lngLat1 = [
      Cesium.Math.toDegrees(c1.longitude),
      Cesium.Math.toDegrees(c1.latitude),
    ];
    let lngLat2 = [
      Cesium.Math.toDegrees(c2.longitude),
      Cesium.Math.toDegrees(c2.latitude),
    ];

    let lngLat3 = [
      Cesium.Math.toDegrees(c1.longitude),
      Cesium.Math.toDegrees(c2.latitude),
    ];
    let lngLat4 = [
      Cesium.Math.toDegrees(c2.longitude),
      Cesium.Math.toDegrees(c1.latitude),
    ];

    return [lngLat1, lngLat3, lngLat2, lngLat4];
  }

  // 绘制多边形
  generatePolygon() {
    this.drawEntity = this.viewer.entities.add({
      Type: this.DrawTypes.Polygon,
      polygon: {
        // 多边形坐标有首位闭合的特点
        hierarchy: new Cesium.CallbackProperty((e) => {
          return new Cesium.PolygonHierarchy(
            this.curPositions.concat(this.curPositions[0])
          );
        }, false),
        material: Cesium.Color.RED.withAlpha(0.6)
      },
      polyline: {
        positions: new Cesium.CallbackProperty((e) => {
          return this.curPositions.concat(this.curPositions[0]);
        }, false),
        width: 1,
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.YELLOW,
        }),
        depthFailMaterial: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.YELLOW,
        })
      },
    });
  }

  // 绘制圆
  generateCircle() {
    this.drawEntity = this.viewer.entities.add({
      position: this.positions[0],
      ellipse: {
        height: this.positionTool.getPositionHeight(this.positions[0]),
        semiMinorAxis: new Cesium.CallbackProperty((e) => {
          return this.getAxis();
        }, false),
        semiMajorAxis: new Cesium.CallbackProperty((e) => {
          return this.getAxis();
        }, false),
        material: Cesium.Color.RED.withAlpha(0.6),
      },
    });
  }

  //圆半径
  getAxis() {
    if (this.curPositions.length>1) {
      let p1 = this.curPositions[0];
      let p2 = this.curPositions[this.curPositions.length - 1];
      const axis = Cesium.Cartesian3.distance(p1, p2);
      return axis;
    }else{
      return 0
    }
  }

  // 结束绘制
  deactive() {
    // 对于圆,根据半径计算边缘点坐标并返回
    let points = [];
    if (this.drawType === this.DrawTypes.Circle) {
      const radius = this.getAxis();
      const positions = this.positionTool.cartesian3ToDegreesHeight(this.positions[0]);
      points = this.positionTool.generateCirclePoints(positions, radius);
      points = points.map((item) => {
        const height = this.positionTool.getPositionHeight(this.positions[0]);
        return Cesium.Cartesian3.fromDegrees(item[0], item[1], height);
      });
    }

    // 提交绘制结束事件
    this.DrawEndEvent.raiseEvent(
      this.drawEntity,
      this.positions,
      this.drawType,
      points
    );
    this.unRegisterEvents();
    this.destoryMarker();
    this.drawType = undefined;
    this.drawEntity = undefined;
    this.positions = [];
    this.curPositions = [];
    this.viewer._element.style.cursor = "pointer";
    this.viewer.enableCursorStyle = true;
  }

  //解除鼠标事件
  unRegisterEvents() {
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    this.handler.removeInputAction(
      Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    );
  }

  //   清除绘制的实体
  removeAllDrawEnts() {
    this.points &&
      this.points.forEach((point) => {
        this.viewer.entities.remove(point);
      });
    this.drawEntity && this.viewer.entities.remove(this.drawEntity);
    this.points = [];
    this.drawEntity = null;
  }

  removeListener(event) {
    this.DrawEndEvent &&
      this.DrawEndEvent.numberOfListeners &&
      this.DrawEndEvent.removeEventListener(event);
  }
}

export default DrawTool;

  DrawToolUse.js

import * as Cesium from 'cesium'
import * as dat from 'dat.gui'
import DrawTool from '../lib/DrawTool'

const gui=new dat.GUI()
// Cesium Ion token
Cesium.Ion.defaultAccessToken='mytoken'
// viewer是整个三维场景的入口
const viewer=new Cesium.Viewer('cesiumContainer',{
    // 隐藏默认显示的控件
    // 时间轴控件
    timeline:false,
    // 动画控件
    animation:false,
    // 设置底图切换控件
    baseLayerPicker:false,
    // 复位按钮的控件
    homeButton:false,
    // 全屏按钮的控件
    fullscreenButton:false,
    // 导航功能的控件
    geocoder:false,
    // 隐藏二三维模式的切换控件
    sceneModePicker:false,
    scene3DOnly:true,
    // 隐藏默认的导航按钮
    navigationHelpButton:false,
    // 时间是否流动
    shouldAnimate:true,
    imageryProvider:new Cesium.GridImageryProvider({
        cells:1,
        glowWidth:0,
        color:Cesium.Color.WHITE.withAlpha(0.1),
        backgroundColor:Cesium.Color.GRAY
    })
})


const drawTool=new DrawTool(viewer)

gui.add({
    fn(){
        drawTool.active(drawTool.DrawTypes.Polyline)
        drawTool.DrawEndEvent.addEventListener((ent,positions)=>{
            console.log(positions);
        })
    }
},'fn').name('绘制线')

gui.add({
    fn(){
        drawTool.active(drawTool.DrawTypes.Polygon)
        drawTool.DrawEndEvent.addEventListener((ent,positions)=>{
            console.log(positions);
        })
    }
},'fn').name('绘制多边形')

http://www.dtcms.com/a/107565.html

相关文章:

  • IO 端口与 IO 内存
  • 电流与电压的守护者
  • 3. 矩阵置零
  • Vue + Axios + Mock.js 全链路实操:从封装到数据模拟的深度解析
  • 两种方法证明r(A+B)<=r(A,B)<=r(A)+r(B)
  • 【一起来学kubernetes】33、Hpa使用详解
  • 常见操作系统特点及区别对比
  • 双翌闪耀2025上海机器视觉展,以创新技术赋能产业未来
  • C++中的继承
  • P2782 友好城市
  • 私有云(三)双节点部署openstack
  • 自学-C语言-基础-数组、函数、指针、结构体和共同体、文件
  • 111.在 Vue 3 中使用 OpenLayers 实现动态曲线流动图(类似 ECharts 迁徙状态)
  • 从代码学习深度学习 - 残差网络(ResNet)PyTorch版
  • MSVC编译遇到C2059、C2143、C2059、C2365、C2059等错误的解决方案
  • 打开pycharm显示编制索引后卡死
  • C++软件开发架构
  • llm-universe 踩坑记录
  • 数值与字典解决方案第二十五讲:数组的合并拆分及筛选
  • GNSS信号模拟器、导航信号模拟器、导航模拟信号源介绍
  • 如何解决 PyQt5 中的 `xcb` 插件加载错误
  • vue修饰符
  • ns-3使用animation出现文件小、无时间、打开后只有拓扑没有内容
  • 《静默与轰鸣的对决》
  • 什么是向量搜索Vector Search?
  • work03_1 实现一个简单的计算器,能够处理加法、减法、乘法和除法
  • 四、Bug篇+用例篇
  • Docker学习--容器操作相关命令--docker inspect 命令
  • C/C++指针核心难点全解析:从内存模型到实战避坑指南
  • AttributeError: module ‘smtplib‘ has no attribute ‘SMTP_SSL‘ 解决方法