Cesium 自定义Primitive - 绘制线

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

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

一、创作来源

        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;
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

生活真难

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

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

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

打赏作者

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

抵扣说明:

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

余额充值