Cesium 自定义Primitive - 绘制矩形

本文介绍了如何在Cesium中使用CustomRectanglePrimitive和ScreenSpaceEventHandler实现一个动态绘制矩形的工具,包括创建绘制类、处理鼠标点击和移动事件,以及屏幕坐标到地球坐标的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、创作来源

        1、cesium的entity绘制矩形

        2、不使用entity的情况下,使用自定义的primitive来动态绘制矩形

        3、结合上一篇文章的矩形,执行动态矩形的更新

二、编写步骤

1、创建绘制矩形的类

        包括构造函数、绘图函数以及销毁函数

import { Viewer, ScreenSpaceEventHandler, ScreenSpaceEventType } from "cesium";
import { pickPosition } from "@/components/MilitaryPlot/utils/PlotUtils";
import CustomRectanglePrimitive from "@/components/samples/CustomRectanglePrimitive";
export default class DrawRectangleTool {
  /**
   * 构造函数
   * @param {Viewer} viewer
   */
  constructor(viewer) {
    /**
     * 地球视图
     * @type {Viewer}
     * @private
     */
    this._viewer = viewer;
    /**
     * 线对象
     * @type {CustomRectanglePrimitive}
     * @private
     */
    this._primitive = undefined;
    /**
     * 事件
     * @type {ScreenSpaceEventHandler}
     * @private
     */
    this._handler = undefined;
  }

  /**
   * 绘图
   */
  draw() {
  }
  /**
   * 销毁
   */
  destroy() {
    if (this._handler) {
      this._handler.isDestroyed() && this._handler.destroy();
      this._handler = null;
    }
  }
}

 2、事件确认

        鼠标点击事件、移动事件

  /**
   * 绘图
   */
  draw() {
    this._handler = new ScreenSpaceEventHandler(this._viewer.canvas);
    let positions = [];
    let flag = this;
    this._handler.setInputAction((event) => {
      console.log("左键单机事件");
    }, ScreenSpaceEventType.LEFT_CLICK);
    this._handler.setInputAction((event) => {
      console.log("鼠标移动事件");
    }, ScreenSpaceEventType.MOUSE_MOVE);
  }

3、点位变动逻辑

        =>初始为空的数组

        =>点击后当为空时直接push,当有两个点时,结束编辑

        =>移动:当只有一个点时直接push,当点位数大于1的时候,先移除后push

4、屏幕坐标转地球坐标

        

/**
 * 获取地图点位
 * @param {Cartesian2} screenPosition 屏幕坐标
 * @param {Viewer} viewer 地图
 * @returns {Cartesian3} 地图三维坐标
 */
export const pickPosition = (screenPosition, viewer) => {
  let ray = viewer.camera.getPickRay(screenPosition);
  return viewer.scene.globe.pick(ray, viewer.scene);
};

5、鼠标事件代码

/**
   * 绘图
   */
  draw() {
    this._handler = new ScreenSpaceEventHandler(this._viewer.canvas);
    let positions = [];
    let flag = this;
    this._handler.setInputAction((event) => {
      console.log("左键单机事件");
      let position = pickPosition(event.position, flag._viewer);
      if (position) {
        if (positions.length === 0) {
          positions.push(position);
        } else {
          positions.pop();
          positions.push(position);
        }
      }
    }, ScreenSpaceEventType.LEFT_CLICK);
    this._handler.setInputAction((event) => {
      console.log("鼠标移动事件");
      let position = pickPosition(event.endPosition, flag._viewer);
      if (position) {
        if (positions.length === 1) {
          positions.push(position);
        } else if (positions.length > 1) {
          positions.pop();
          positions.push(position);
        }
      }
    }, ScreenSpaceEventType.MOUSE_MOVE);
  }

 6、渲染矩形代码

/**
   * 绘图
   */
  draw() {
    this._handler = new ScreenSpaceEventHandler(this._viewer.canvas);
    let positions = [];
    let flag = this;
    this._handler.setInputAction((event) => {
      console.log("左键单机事件");
      let position = pickPosition(event.position, flag._viewer);
      if (position) {
        if (positions.length === 0) {
          positions.push(position);
          flag._primitive = new CustomRectanglePrimitive({});
          this._viewer.scene.primitives.add(this._primitive);
        } else {
          positions.pop();
          positions.push(position);
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
          this._primitive = undefined;
          positions = [];
        }
      }
    }, ScreenSpaceEventType.LEFT_CLICK);
    this._handler.setInputAction((event) => {
      console.log("鼠标移动事件");
      let position = pickPosition(event.endPosition, flag._viewer);
      if (position) {
        if (positions.length === 1) {
          positions.push(position);
        } else if (positions.length > 1) {
          positions.pop();
          positions.push(position);
        }
        if (flag._primitive) {
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
        }
      }
    }, ScreenSpaceEventType.MOUSE_MOVE);
  }

7、测试

let tool = new DrawRectangleTool(viewer);
tool.draw();

三、实现效果

四、代码

import { Viewer, ScreenSpaceEventHandler, ScreenSpaceEventType } from "cesium";
import { pickPosition } from "@/components/MilitaryPlot/utils/PlotUtils";
import CustomRectanglePrimitive from "@/components/samples/CustomRectanglePrimitive";
export default class DrawRectangleTool {
  /**
   * 构造函数
   * @param {Viewer} viewer
   */
  constructor(viewer) {
    /**
     * 地球视图
     * @type {Viewer}
     * @private
     */
    this._viewer = viewer;
    /**
     * 线对象
     * @type {CustomRectanglePrimitive}
     * @private
     */
    this._primitive = undefined;
    /**
     * 事件
     * @type {ScreenSpaceEventHandler}
     * @private
     */
    this._handler = undefined;
  }

  /**
   * 绘图
   */
  draw() {
    this._handler = new ScreenSpaceEventHandler(this._viewer.canvas);
    let positions = [];
    let flag = this;
    this._handler.setInputAction((event) => {
      console.log("左键单机事件");
      let position = pickPosition(event.position, flag._viewer);
      if (position) {
        if (positions.length === 0) {
          positions.push(position);
          flag._primitive = new CustomRectanglePrimitive({});
          this._viewer.scene.primitives.add(this._primitive);
        } else {
          positions.pop();
          positions.push(position);
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
          this._primitive = undefined;
          positions = [];
        }
      }
    }, ScreenSpaceEventType.LEFT_CLICK);
    this._handler.setInputAction((event) => {
      console.log("鼠标移动事件");
      let position = pickPosition(event.endPosition, flag._viewer);
      if (position) {
        if (positions.length === 1) {
          positions.push(position);
        } else if (positions.length > 1) {
          positions.pop();
          positions.push(position);
        }
        if (flag._primitive) {
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
        }
      }
    }, ScreenSpaceEventType.MOUSE_MOVE);
  }
  /**
   * 销毁
   */
  destroy() {
    if (this._handler) {
      this._handler.isDestroyed() && this._handler.destroy();
      this._handler = null;
    }
  }
}

你可以使用Cesium的`Primitive`类来绘制大量的元素,并通过点击事件进行对象的拾取。下面是一个简单的示例代码,演示了如何使用`Primitive`来实现这个功能: ```javascript // 创建场景 var viewer = new Cesium.Viewer('cesiumContainer'); // 定义一个自定义primitive var customPrimitive = new Cesium.Primitive({ geometryInstances : new Cesium.GeometryInstance({ geometry : new Cesium.RectangleGeometry({ rectangle : Cesium.Rectangle.fromDegrees(-120.0, 20.0, -60.0, 40.0) }), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED) } }), appearance : new Cesium.EllipsoidSurfaceAppearance({ aboveGround : false }) }); // 添加primitive到场景 viewer.scene.primitives.add(customPrimitive); // 监听鼠标点击事件 var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas); handler.setInputAction(function(movement) { var pickedObject = viewer.scene.pick(movement.position); if (Cesium.defined(pickedObject)) { // 处理拾取到的对象 console.log('Picked object:', pickedObject); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); ``` 在上面的示例中,我们首先创建了一个`Cesium.Viewer`对象来展示Cesium场景。然后,我们创建了一个自定义的`Primitive`,该示例中使用`RectangleGeometry`来绘制一个矩形,并指定了颜色属性。接下来,我们将这个自定义的`Primitive`添加到场景中。最后,我们使用`ScreenSpaceEventHandler`来监听鼠标左键点击事件,并通过`scene.pick`方法获取被点击的对象。 你可以根据自己的需求修改示例代码中的几何形状、颜色和点击事件的处理逻辑。希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生活真难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值