Cesium 自定义Primitive - 绘制线

本文介绍了如何使用Cesium库中的CustomPolylinePrimitive绘制线,并利用ScreenSpaceEventHandler处理鼠标事件,如左键点击、鼠标移动和右键结束编辑,实现动态线绘制和更新功能。
摘要由CSDN通过智能技术生成

一、创作来源

        1、cesium的entity绘制线

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

        3、结合上一篇文章的动态绘制线,执行动态线的更新

二、ScreenSpaceEventHandler

        1、概念

        cesium中的用户输入事件:ScreenSpaceEventHandler,处理用户输入事件。可以添加自定义功能以在用户输入时执行。

        API地址:CesiumApi传送门

        2、事件类型

        红色部分为常用类型

        

        3、方法

        destroy()

        移除此对象持有的侦听器。

        isDestroyed()

        如果此对象被销毁,则返回 true;否则为false。

        getInputAction(type, modifier)

        返回要在输入事件上执行的函数。

        removeInputAction(type, modifier)

        删除要在输入事件上执行的函数。

        setInputAction(action, type, modifier)

        设置要在输入事件上执行的功能。

       4、示例

        a、左键单击

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
	console.log('shift + 左键单击', event.position); 
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

         b、鼠标移动事件

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
    console.log('shift + 鼠标移动', event.position); 
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        c、右键事件

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
	console.log('shift + 右键单击', event.position); 
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

三、编写步骤

1、创建绘制线的类

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

import { Viewer, ScreenSpaceEventHandler } from "cesium";
export default class DrawPolylineTool {
  /**
   * 构造函数
   * @param {Viewer} viewer
   */
  constructor(viewer) {
    /**
     * 地球视图
     * @type {Viewer}
     * @private
     */
    this._viewer = viewer;
    /**
     * 线对象
     * @type {CustomPolylinePrimitive}
     * @private
     */
    this._primitive = undefined;
    /**
     * 事件
     * @type {ScreenSpaceEventHandler}
     * @private
     */
    this._handler = undefined;
  }
  draw() {}
  destroy() {}
}

2、事件确认

        鼠标点击事件、移动事件、右键结束编辑

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

  /**
   * 绘图
   */
  draw() {
    this._handler = new ScreenSpaceEventHandler(this._viewer.canvas);
    this._handler.setInputAction((event) => {
      console.log("左键单机事件");
    }, ScreenSpaceEventType.LEFT_CLICK);
    this._handler.setInputAction((event) => {
      console.log("鼠标移动事件");
    }, ScreenSpaceEventType.MOUSE_MOVE);
    this._handler.setInputAction((event) => {
      console.log("鼠标右键单机事件");
    }, ScreenSpaceEventType.RIGHT_CLICK);
  }
  /**
   * 销毁
   */
  destroy() {
    if (this._handler) {
      this._handler.isDestroyed() && this._handler.destroy();
      this._handler = null;
    }
  }
}

 3、点位变动逻辑

        =>初始为空的数组

        =>点击后当为空时直接push,当有两个点时,先pop后push

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

        =>右键直接结束

4、代码实现

        1、屏幕坐标转地球坐标

/**
 * 获取地图点位
 * @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);
};

        2、鼠标事件代码

/**
   * 绘图
   */
  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);
    this._handler.setInputAction((event) => {
      console.log("鼠标右键单机事件");
      this._primitive = undefined;
      positions = [];
    }, ScreenSpaceEventType.RIGHT_CLICK);
  }

            3、渲染线代码

/**
   * 绘图
   */
  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 CustomPolylinePrimitive();
          this._viewer.scene.primitives.add(this._primitive);
        } else {
          let moveP = positions.pop();
          positions.push(position, moveP);
        }
        if (flag._primitive) {
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
        }
      }
    }, 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);
    this._handler.setInputAction((event) => {
      console.log("鼠标右键单机事件");
      if (flag._primitive) {
        flag._primitive.updateProperty({
          positions: [...positions],
          complete: false,
        });
      }
      this._primitive = undefined;
      positions = [];
    }, ScreenSpaceEventType.RIGHT_CLICK);
  }

        4、测试

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

四、演示结果

      

五、全部代码

import { Viewer, ScreenSpaceEventHandler, ScreenSpaceEventType } from "cesium";
import { pickPosition } from "@/components/MilitaryPlot/utils/PlotUtils";
import CustomPolylinePrimitive from "@/components/entity/CustomPolylinePrimitive";
export default class DrawPolylineTool {
  /**
   * 构造函数
   * @param {Viewer} viewer
   */
  constructor(viewer) {
    /**
     * 地球视图
     * @type {Viewer}
     * @private
     */
    this._viewer = viewer;
    /**
     * 线对象
     * @type {CustomPolylinePrimitive}
     * @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 CustomPolylinePrimitive();
          this._viewer.scene.primitives.add(this._primitive);
        } else {
          let moveP = positions.pop();
          positions.push(position, moveP);
        }
        if (flag._primitive) {
          flag._primitive.updateProperty({
            positions: [...positions],
            complete: false,
          });
        }
      }
    }, 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);
    this._handler.setInputAction((event) => {
      console.log("鼠标右键单机事件");
      if (flag._primitive) {
        flag._primitive.updateProperty({
          positions: [...positions],
          complete: false,
        });
      }
      this._primitive = undefined;
      positions = [];
    }, ScreenSpaceEventType.RIGHT_CLICK);
  }
  /**
   * 销毁
   */
  destroy() {
    if (this._handler) {
      this._handler.isDestroyed() && this._handler.destroy();
      this._handler = null;
    }
  }
}

  • 34
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
你可以使用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、付费专栏及课程。

余额充值