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

news2024/11/24 17:25:36

前言

如果你是在寻求解决方案,可以直接用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)绘制多段线(动态实时画线)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1004298.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安防监控/视频汇聚/云存储/AI智能视频分析平台EasyCVR下级海康设备无法级联是什么原因?

安防视频监控平台/视频集中存储/云存储/磁盘阵列EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。 有用户反馈&…

Excel、Jira、Bugfree 应该选哪个做bug管理?深度对比

如何选择最适合您团队的Bug管理系统&#xff1f;本指南提供了全面的选型建议&#xff0c;并深度对比了7类主流工具如PingCode、Jira、 Mantis等&#xff0c;涵盖功能、成本、易用性等多个关键因素。适用于软件开发团队、项目经理和决策者。 一、适合的BUG管理工具在产品开发中的…

华为云云耀云服务器L实例评测|在云耀云服务器L实例上部署经典小游戏battle-city坦克大战

文章目录 1 引言2 购买云耀云服务器2.1 华为账号2.2 华为云耀云服务器L实例 3 登录云服务器3.1 重置密码3.2 远程登录 4 安装Node.js4.1 下载4.2 解压4.3 环境配置4.4 确认Node版本4.5 其他 5 部署经典小游戏battle-city坦克大战5.1 下载5.2 安装5.3 启动游戏服务 6 在线访问ba…

如何实现CSDN评论区粉丝幸运抽选功能:一场代码与运气的碰撞

文章目录 前言抽选规则实现思路代码实现1.获取评论数据2.过滤符合抽选规则的评论者3.获取粉丝数据4.过滤符合抽选规则的粉丝5.增加公众号留言权重6.抽选粉丝 完整的代码效果展示结语 前言 为了回馈粉丝们一直以来的的关注和支持&#xff0c;我近期开启了赠书活动&#xff0c;活…

使用 Nginx 实现企业微信域名配置中的校验文件跳转

背景 在企业微信中配置业务域名时&#xff0c;通常需要在该域名的根路径下放置一个校验文件&#xff0c;以验证域名的所有权。然而&#xff0c;如果该域名是第三方的&#xff0c;你可能无法直接在根路径下放置文件。在这种情况下&#xff0c;你可以使用 Nginx 来实现校验文件的…

软件测试/测试开发丨使用ChatGPT自动进行需求分析

简介 在实际工作过程中&#xff0c;常常需要拿到产品的PRD文档或者原型图进行需求分析&#xff0c;为产品的功能设计和优化提供建议。 而使用ChatGPT可以很好地帮助分析和整理用户需求。 实践演练 接下来&#xff0c;需要使用ChatGPT 辅助我们完成需求分析的任务 注意&…

pgsql操作json类型

目录 一、表结构 二、实体类 三、json处理器 四、配置文件 五、josn数据 1、插入 2、查找 一、表结构 CREATE TABLE "public"."pg_user" ("id" int8 NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 MINVALUE 1 MAXVALUE 92233720…

肖sir__mysql之navicat安装__003

navicat 工具 一、navicat 介绍 &#xff1a;Navicat是一套可创建多个连接的数据库管理工具&#xff0c;用以方便管理 MySQL&#xff0c;创建、管理和维护数据库 二、navicat安装 1、安装包 2、查看navicat中安装包&#xff0c;并创建快捷方式 3、创建快捷键图标&#xff1a…

Vue3 学习-组件通讯(二)

文章目录 前言一、props通信二、自定义事件&#xff08;emit&#xff09;三、全局事件总线(EventBus)四、v-model五、userAttrs六、ref和$parent七、Provide与Inject八、pinia九、slot插槽总结 前言 本文主要记录Vue3的九种组件通信方式 一、props通信 子组件需要用defineProp…

MCU主频 服务器台式机主频 处理器主频那些事

几十M级别的 几百M级别的 几个G级别 早期的典型的51单片机外部接12MHz晶振&#xff0c;内部电路对12MHz的原始时钟进行12分频变成1MHz的时钟给CPU&#xff0c;所以早期典型的51内核的主频是1MHz。后来工艺改良了单片机也设计也改良了&#xff0c;CPU可以耐受的主频提升了&am…

【Unity3D】UI Toolkit数据动态绑定

1 前言 本文将实现 cvs 表格数据与 UI Toolkit 元素的动态绑定。 如果读者对 UI Toolkit 不是太了解&#xff0c;可以参考以下内容。 UI Toolkit简介UI Toolkit容器UI Toolkit元素UI Toolkit样式选择器UI Toolkit自定义元素 本文完整资源见→UI Toolkit数据动态绑定。 2 数据…

如何制作医疗科普宣传片

科普宣传片通过视觉呈现、简化浓缩、故事叙述、情感引导等手段&#xff0c;将科学知识生动地传达给观众&#xff0c;覆盖广泛的传播渠道使其影响力更大。制作医疗科普宣传片需要综合考虑目标受众、内容传递、专业性和吸引力等因素。下面是一些制作医疗科普宣传片的步骤和建议&a…

在滴滴和字节划水四年半,太真实了...

先简单交代一下吧&#xff0c;沅哥是某不知名211的本硕&#xff0c;18年毕业加入滴滴&#xff0c;之后跳槽到了头条&#xff0c;一直从事测试开发相关的工作。之前没有实习经历&#xff0c;算是四年半的工作经验吧。 这四年半之间他完成了一次晋升&#xff0c;换了一家公司&am…

【数据结构-二叉树】二叉树

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

什么是软件测试?5分钟带你快速了解!

经常有人问我&#xff0c;你的公司是做什么的&#xff1f;我回答“软件测试”&#xff0c;看着对方一脸的迷茫。何为软件测试&#xff1f;软件测试究竟测试什么&#xff1f; 一、软件测试的定义和意义 软件测试是伴随着软件工程的重要组成部分&#xff0c;是软件质量保证的重…

在python程序中用windows的icon

这个exe的弹窗功能会使用到一个ico文件&#xff0c;如图&#xff1a; 用软件GreenfishIconEditorProPortable或者使用在线软件将你需要的图片制作成windows的icon 用程序将ico文件生成文本文件 import base64picture_name "logo.ico" open_pic open("%s…

VirtualBox宿主机和虚拟机文件互传设置

一、如图1、2、3步骤&#xff0c;设置共享粘贴板和拖放为双向 二、 在启动的虚拟机设置的里面&#xff0c;安装增强插件&#xff0c;然后重启虚拟机。 三、在网络位置就可以看到了

十种数据库缓存相关的技术和机制

数据库的缓存 -- 通过将数据库中的数据或结果集保存在内存或其他快速访问的介质中&#xff0c;能够加快查询响应&#xff0c;减少对磁盘或远程服务器的访问&#xff0c;降低资源消耗。 根据缓存的位置、内容、粒度、更新方式等不同&#xff0c;数据库缓存技术有多种类型和策略。…

NAT(网络地址转换)

文章目录 一、产生背景二、公有地址和私有地址三、定义四、分类五、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、产生背景 IPv4公网地址资源耗尽&#xff1a; 由于IPv4地址空间有限&#xff0c;公网IPv4地址资源逐渐耗尽&#xff0c;导致难以分…

图像尺寸测量仪:解析适用零部件与应用领域

图像尺寸测量仪也叫一键测量仪器&#xff0c;全自动闪测仪等&#xff0c;是一种精密二次元测量仪器。它能够精确测量各种零部件的形状和尺寸&#xff0c;核心优势在于测量大批量小型精密零部件&#xff0c;这对于质量控制和生产流程的优化至关重要。 图像尺寸测量仪适用于哪些…