cesium 实现自定义弹窗并跟随场景移动

cesium 添加点位自定义弹窗跟随场景移动 完整代码演示可直接copy使用

1 效果图:

2 深入理解

就是原始点位的数据

id>property

点位真实渲染到球体上的笛卡尔坐标系

id>_polyline 的路径下 可以通过

3 代码示例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.85/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
  <script src="https://unpkg.com/@turf/turf/turf.min.js"></script>
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.85/Build/Cesium/Cesium.js"></script>
  <script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
</head>

<body>
  <div id="app">
    <button @click="mapClick">主动触发点位弹窗</button>
    <button @click="removeLayer('site_layer')">清除点位图层</button>
    <div id="cesiumContainer">
      <div id="popup">
        <div class="cesium-popup" @closeMap="closeMapPop" v-if="popVisible" ref="overlay">
          <div class="pop_header">
            <p class="rhpk_info"> {{ overlayChartObj.name }}基本信息</p>
            <div class="map_close" @click="closeMapPop">x</div>
          </div>
          <sitePop>
            <div class="button_box">
              <div>自动监测</div>
            </div>
          </sitePop>
        </div>
      </div>
    </div>
  </div>

  <script>
    var viewer = null
    new Vue({
      el: '#app',
      data: {
        popVisible: false,
        overlayChartObj: {},
        list: [
          { longitude: 109.306058, latitude: 30.86751, id: 0, name: "标点一" },
          { longitude: 109.306058, latitude: 30.56751, id: 1, name: "标点二" },
        ]
      },
      mounted() {
        this.mapCreate()
      },
      methods: {
        async mapCreate() {
          Cesium.Ion.defaultAccessToken =
            "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2ZjZlMzAxNS1jY2ZmLTQ0MzctYTE1MS0zNzMxZjhkZjlhYTgiLCJpZCI6MTIyNTg4LCJpYXQiOjE2NzQ5NzMxNTB9.GKIVHIsKN-AWd4vjLOIPm9Fji8tIEvZd5AXf-rTvFk0";
          viewer = new Cesium.Viewer('cesiumContainer', {
            geocoder: false,
            homeButton: false, 
            animation: false, 
            fullscreenButton: false,
            sceneModePicker: false,
            timeline: true, 。
            navigationHelpButton: false, 
            baseLayerPicker: false, 
            infoBox: false, 
            scene3DOnly: false, 
            selectionIndicator: false,
            baselLayerPicker: false,
          });
          let terrainProvider = Cesium.createWorldTerrain({ //添加世界地形能看到山脉的高低起伏
            requestVertexNormals: true, //开启地形光照
            requestWaterMask: true, // 开启水面波纹
          });
          viewer.terrainProvider = terrainProvider;
          viewer.debugShowFramesPerSecond = true//显示当前的帧率信息,这样你就可以实时观察到地图的渲染性能
          viewer.scene.screenSpaceCameraController.minimumZoomDistance = 1;// 设置了摄像机的最小缩放距离
          viewer.camera.setView({ // 相机视口
            destination: Cesium.Cartesian3.fromDegrees(109.306058, 30.86751, 8000),
            orientation: {
              heading: Cesium.Math.toRadians(0), //控制视口左右旋转,也就是沿Y轴旋转,0时为正北方向
              pitch: Cesium.Math.toRadians(-25), // 控制视口上下旋转,也就是沿X轴旋转,-90时为俯视地面
              roll: 0, // 控制视口翻转角度,也就是沿Z轴旋转,0时为不翻转
            },
            //奉节 坐标
          });
          this.handlePinClick(); // 注册点位点击事件
          this.bindMapMove(); // 注册场景移动事件
          this.renderSiteCesiumPoint(this.list)
        },
      }
    })
  </script>

</body>

</html>

完整代码示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link href="https://cesium.com/downloads/cesiumjs/releases/1.85/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><script src="https://unpkg.com/@turf/turf/turf.min.js"></script><script src="https://cesium.com/downloads/cesiumjs/releases/1.85/Build/Cesium/Cesium.js"></script><script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script><style>#cesiumContainer {width: 1920px;height: 1080px;}#cesiumContainer .cesium-widget-credits {display: none;}.cesium-popup {position: relative;width: 267px;min-height: 152px;background: pink;/* background: url(~@/assets/images/mapPop.png) no-repeat; */background-size: cover;}.cesium-popup .pop_header {width: 431px;height: 57px;line-height: 57px;/* background: url(~@/assets/images/mapHeader.png) no-repeat 100% 100%; */}.cesium-popup .rhpk_info {font-size: 18px;font-weight: bold;color: #fff;padding-left: 70px;box-sizing: border-box;}.cesium-popup .map_close {position: absolute;top: 16px;right: 20px;width: 29px;height: 29px;/* background: url(~@/assets/images/mapClose.png) no-repeat 100% 100%; */cursor: pointer;}.cesium-popup .map_con {padding: 20px 20px;width: 100%;box-sizing: border-box;}.cesium-popup .info {display: flex;font-size: 16px;color: #fff;margin-bottom: 20px;}.cesium-popup .title {width: 85px;font-weight: 400;color: #57bcd2;}.cesium-popup .button_box {position: absolute;bottom: 30px;left: 0px;width: 100%;display: flex;justify-content: flex-end;}.cesium-popup .button_box div {width: 100px;height: 27px;/* background: url(~@/assets/images/mapButton.png) no-repeat 100% 100%; */line-height: 27px;text-align: center;cursor: pointer;margin: 0 10px;}</style>
</head><body><div id="app"><button @click="mapClick">主动触发点位弹窗</button><button @click="removeLayer('site_layer')">清除点位图层</button><div id="cesiumContainer"><div id="popup"><div class="cesium-popup" @closeMap="closeMapPop" v-if="popVisible" ref="overlay"><div class="pop_header"><p class="rhpk_info"> {{ overlayChartObj.name }}基本信息</p><div class="map_close" @click="closeMapPop">x</div></div><sitePop><div class="button_box"><div>自动监测</div></div></sitePop></div></div></div></div><script>var viewer = nullnew Vue({el: '#app',data: {popVisible: false,overlayChartObj: {},list: [{ longitude: 109.306058, latitude: 30.86751, id: 0, name: "标点一" },{ longitude: 109.306058, latitude: 30.56751, id: 1, name: "标点二" },]},mounted() {this.mapCreate()},methods: {async mapCreate() {Cesium.Ion.defaultAccessToken ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2ZjZlMzAxNS1jY2ZmLTQ0MzctYTE1MS0zNzMxZjhkZjlhYTgiLCJpZCI6MTIyNTg4LCJpYXQiOjE2NzQ5NzMxNTB9.GKIVHIsKN-AWd4vjLOIPm9Fji8tIEvZd5AXf-rTvFk0";viewer = new Cesium.Viewer('cesiumContainer', {geocoder: false,homeButton: false, animation: false, fullscreenButton: false,sceneModePicker: false,timeline: true, 。navigationHelpButton: false, baseLayerPicker: false, infoBox: false, scene3DOnly: false, selectionIndicator: false,baselLayerPicker: false,});let terrainProvider = Cesium.createWorldTerrain({ //添加世界地形能看到山脉的高低起伏requestVertexNormals: true, //开启地形光照requestWaterMask: true, // 开启水面波纹});viewer.terrainProvider = terrainProvider;var lastCameraHeight = 0;var heightStableCount = 0;var threshold = 5; // 高度稳定的阈值var maxStableCount = 30; // 达到稳定的帧数function isTerrainProvider() {var cameraHeight =viewer.camera.positionCartographic.height;if (Math.abs(cameraHeight - lastCameraHeight) < threshold) {heightStableCount++;} else {heightStableCount = 0;}if (heightStableCount >= maxStableCount) {console.log("地形加载完成");// 在这里执行地形加载完成后的操作viewer.scene.preRender.removeEventListener(isTerrainProvider);}lastCameraHeight = cameraHeight;}viewer.debugShowFramesPerSecond = true//显示当前的帧率信息,这样你就可以实时观察到地图的渲染性能viewer.scene.screenSpaceCameraController.minimumZoomDistance = 1;// 设置了摄像机的最小缩放距离viewer.camera.setView({ // 相机视口destination: Cesium.Cartesian3.fromDegrees(109.306058, 30.86751, 8000),orientation: {heading: Cesium.Math.toRadians(0), //控制视口左右旋转,也就是沿Y轴旋转,0时为正北方向pitch: Cesium.Math.toRadians(-25), // 控制视口上下旋转,也就是沿X轴旋转,-90时为俯视地面roll: 0, // 控制视口翻转角度,也就是沿Z轴旋转,0时为不翻转},//奉节 坐标});this.handlePinClick(); // 注册点位点击事件this.bindMapMove(); // 注册场景移动事件this.renderSiteCesiumPoint(this.list)},renderSiteCesiumPoint(projectList) {this.removeLayer('site_layer')for (let i = 0; i < projectList.length; i++) {const pro = projectList[i];let longitude = pro.longitude || 0let latitude = pro.latitude || 0let imgUrl = `./site.png`;viewer.entities.add({position: Cesium.Cartesian3.fromDegrees( // 设置点位的经纬度和高度longitude,latitude,240),name: pro.name,id: `site_layer_${pro.id}`, // site_layer就是自定义layerName后续可通过这个移除property: pro,polyline: {show: true, //是否显示,默认显示// 关键点在设置一条竖直的线positions: Cesium.Cartesian3.fromDegreesArrayHeights([longitude,latitude,0,longitude,latitude,240,]),width: 1, //线的宽度(像素),默认为1material: Cesium.Color.fromCssColorString("#069BBF").withAlpha(1),},billboard: {width: 33, // 点位的大小height: 33,image: imgUrl,verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置垂直方向的对齐方式},});}},removeLayer(layerName) { // 根据图层名移除对应的图层组let entityList = [];let count = 0while (count < 8) {viewer.entities.values.forEach(function (entity) {if (entity._id.includes(layerName)) {viewer.entities.remove(entity);}});count++;}},// 点击地图上的点handlePinClick(data = null, typePop = null) {const cesiumViewer = viewer;const tt = this;if (data != null && typePop != null) {console.log('主动触发', data, typePop)tt.overlayChartObj = Object.assign(data, {layer: typePop});tt.getProjDetailPop({x: 951.25,y: 600}, data);return}const handle3D = new Cesium.ScreenSpaceEventHandler(cesiumViewer.scene.canvas);handle3D.setInputAction((movement) => {const pick = cesiumViewer.scene.pick(movement.position);console.log("pick===>", pick, pick.id); // pick.id是点击后获取对应的实体console.log("pick===>",pick.id.polyline.positions.value.getValue());if (!pick.id) {console.log("清除监听事件===>", pick, pick.id);this.popVisible = false;// 清除监听事件cesiumViewer.scene.postRender.removeEventListener(this.bindMapMove);return;}const obj = pick.id.property;// 解决点击不同点数据不更换问题if (tt.overlayChartObj != {}) {tt.popVisible = false;tt.overlayChartObj = {};}const coordinate = movement.position;console.log("coordinate===>", coordinate);if (pick.id._id.includes("rhpwk_layer")) {tt.overlayChartObj = Object.assign(obj, {layer: "rhpwk_layer"});tt.getProjDetailPop(coordinate, obj);} else if (pick.id._id.includes("site_layer")) {tt.overlayChartObj = Object.assign(obj, {layer: "site_layer" //使用site_layer类型的点位弹窗});tt.getProjDetailPop(coordinate, obj);} else if (pick.id._id.includes("camera_layer")) {tt.overlayChartObj = Object.assign(obj, {layer: "camera_layer"});tt.getProjDetailPop(coordinate, obj);} else if (pick.id._id.includes("wry_layer")) {tt.overlayChartObj = Object.assign(obj, {layer: "wry_layer"});tt.getProjDetailPop(coordinate, obj);}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);},getProjDetailPop(coordinate, obj) {this.showOverlayChart(coordinate, obj);},// 显示showOverlayChart(position, data) {const pop = document.getElementById("popup");pop.style.position = "absolute";pop.style.top = position.y + "px";pop.style.left = position.x + "px";pop.style.zIndex = 99;this.overlayChartObj = data;this.popVisible = true;},bindMapMove() {const cesiumViewer = viewer;console.log('cesiumViewer', cesiumViewer)const tt = this;cesiumViewer.scene.preRender.addEventListener(() => {if (!tt.popVisible) return;const scratch = Cesium.Cartesian2();const position = Cesium.Cartesian3.fromDegrees(Number(tt.overlayChartObj.longitude),Number(tt.overlayChartObj.latitude),300);const canvasPosition = cesiumViewer.scene.cartesianToCanvasCoordinates(position,scratch);if (Cesium.defined(canvasPosition)) {tt.setPopPosition(canvasPosition);}});},setPopPosition(position) {const pop = document.getElementById("popup");pop.style.top = position.y + "px";pop.style.left = position.x + "px";},closeMapPop() {this.popVisible = false;// 清除监听事件viewer.scene.postRender.removeEventListener(this.bindMapMove);},// 主动触发点位弹窗mapClick() {this.handlePinClick(this.list[0], 'site_layer') // 点位数据 及弹窗类型},}})</script></body></html>

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

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

相关文章

【数据分享】2017-2023年全球范围10米精度土地覆盖数据

土地覆盖数据是我们在各项研究中都非常常用的数据&#xff0c;土地覆盖数据的来源也有很多。之前我们分享过欧空局发布的2020年和2021年的10米分辨率的土地覆盖数据,也分享过我国首套1米分辨率的土地覆盖数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; …

管道液位传感器可以检测哪些液体?

管道液位传感器是一种专门用于检测流动性比较好的液体的传感器装置。它采用光学感应原理&#xff0c;不涉及任何机械运动&#xff0c;具有长寿命、安装方便和微功耗的特点。相比传统机械式液位传感器&#xff0c;光电管道传感器有效解决了低精度和卡死失效等问题&#xff0c;同…

Django 解决 CSRF 问题

在 Django 出现 CSRF 问题 要解决这个问题&#xff0c;就得在 html 里这么修改 <!DOCTYPE html> <html><head></head><body><form action"/login/" method"post">{% csrf_token %}</form></body> </…

短视频脚本创作的五个方法 沈阳短视频剪辑培训

说起脚本&#xff0c;我们大概都听过影视剧脚本、剧本&#xff0c;偶尔可能在某些综艺节目里听过台本。其中剧本是影视剧拍摄的大纲&#xff0c;用来指导影视剧剧情的走向和发展&#xff0c;而台本则是综艺节目流程走向的指导大纲。 那么&#xff0c;短视频脚本是什么&#xf…

探析GPT-4o:技术之巅的跃进

如何评价GPT-4o? 简介&#xff1a;最近&#xff0c;GPT-4o横空出世。对GPT-4o这一人工智能技术进行评价&#xff0c;包括版本间的对比分析、GPT-4o的技术能力以及个人感受等。 随着人工智能领域的不断发展&#xff0c;GPT系列模型一直处于行业的前沿。最近&#xff0c;GPT-4…

前端实习记录——git篇(一些问题与相关命令)

1、版本控制 &#xff08;1&#xff09;版本回滚 git log // 查看版本git reset --mixed HEAD^ // 回滚到修改状态&#xff0c;文件内容没有变化git reset --soft HEAD^ // 回滚暂存区&#xff0c;^的个数代表几个版本git reset --hard HEAD^ // 回滚到修改状态&#xff…

生态农业:引领未来农业新篇章

生态农业&#xff0c;正以其独特的魅力和创新理念&#xff0c;引领着未来农业发展的新篇章。在这个充满变革的时代&#xff0c;我们需要更加关注农业的可持续发展&#xff0c;而生态农业正是实现这一目标的重要途径。 生态农业产业的王总说&#xff1a;生态农业强调生态平衡和可…

【文档+源码+调试讲解】古典舞在线交流平台的设计与实现

摘 要 随着互联网技术的发展&#xff0c;各类网站应运而生&#xff0c;网站具有新颖、展现全面的特点。因此&#xff0c;为了满足用户古典舞在线交流的需求&#xff0c;特开发了本古典舞在线交流平台。 本古典舞在线交流平台应用Java技术&#xff0c;MYSQL数据库存储数据&…

FreeRTOS【7】队列使用

1.开发背景 操作系统提供了多线程并行的操作&#xff0c;为了方便代码的维护&#xff0c;各个线程都分配了专用的内存并处理对应的内容。但是线程间也是需要协助操作的&#xff0c;例如一个主线程接收信息&#xff0c;会把接收的信息并发到其他线程&#xff0c;即主线程不阻塞&…

[LitCTF 2023]yafu (中级) (素数分解)

题目&#xff1a; from Crypto.Util.number import * from secret import flagm bytes_to_long(flag) n 1 for i in range(15):n *getPrime(32) e 65537 c pow(m,e,n) print(fn {n}) print(fc {c})n 152412082177688498871800101395902107678314310182046454156816957…

3D模型展示适合哪些类型的产品?

3D模型展示特别适合那些需要全面展示产品细节和特性的商品&#xff0c;产品3D交互展示具有直观性、动态性、交互性等显著优势&#xff0c;可以通过51建模网一站式完成商品3D建模、3D展示、3D定制、AR试穿等功能&#xff0c;以下是一些适合使用3D模型展示的产品类型&#xff1a;…

npm镜像源管理、nvm安装多版本node异常处理

查看当前使用的镜像源 npm config get registry --locationglobal 设置使用官方源 npm config set registry https://registry.npmjs.org/ --locationglobal 设置淘宝镜像源 npm config set registry https://registry.npm.taobao.org/ --locationglobal 需要更改淘宝镜像源地址…

Java培训后找不到工作,现在去培训嵌入式可行吗?

最近java 工作还是比较好找&#xff0c;不知道你是对薪资要求太高&#xff0c;还是因为其他原因&#xff0c;如果你真的面试了很多都还找不到工作&#xff0c;那么一定要知道找不到工作的原因是啥&#xff0c;一定不是因为java 太卷&#xff0c;你说那个行业&#xff0c;那个职…

多用户协作与实时渲染:3D开发工具HOOPS助力汽车行业CAD可视化

在当今汽车行业&#xff0c;计算机辅助设计&#xff08;CAD&#xff09;可视化是产品设计和开发过程中不可或缺的一环。随着汽车设计复杂性的增加&#xff0c;CAD可视化不仅仅是一个设计工具&#xff0c;更是一个沟通和协作的平台。然而&#xff0c;尽管技术不断进步&#xff0…

Vue3实战笔记(51)—Vue 3封装带均线的k线图

文章目录 前言带均线的k线图总结 前言 继续封装一个封装带均线的k线图 带均线的k线图 EChartsCandlestickSh.vue&#xff1a; <template><div ref"chartContainer" style"width: 100%; height: 500px"></div></template><scr…

西湖大学提出AIGC检测框架,精准识别AI撰写的文稿

近年来人工智能技术突飞猛进&#xff0c;尤其是大语言模型的出现&#xff0c;让AI具备了创作文章、小说、剧本等内容的能力。 AI代写&#xff0c;已经逃不过老师、编辑、审稿人的火眼金睛了。但让AI仅改写部分片段&#xff0c;就安全了么&#xff1f; 针对检测AI改写的片段&a…

新版IDEA没有办法选择Java8版本解决方法

2023年11月27日后&#xff0c;spring.io 默认不再支持创建jdk1.8的项目 解决方法就是把 Spring的Server URL 改为阿里的。 阿里的Server URL https://start.aliyun.com/ 默认的Server URL https://start.spring.io 阿里的Server URL https://start.aliyun.com/

Linux自动重启系统脚本测试工具

前言 脚本允许用户指定重启的次数和重启间隔时间&#xff0c;并自动生成相应的定时任务。通过使用这个脚本&#xff0c;系统管理员可以轻松地设置重启测试。每次重启操作都会被记录下来&#xff0c;以便用户随时了解测试情况。 一、脚本 #!/bin/bashif [ "$1" &qu…

OLED写入指令和数据

1.OLED写命令 写命令/数据的代码 / * 1. start() 2. 写入 b0111 1000 0x78 3. ACK 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据 5. ACK 6. 写入指令/数据 7. ACK 8. STOP */ void Oled_Write_Cmd(char dataCmd)5.1.4 OLED的寻址模式 如何显示一个点&#x…

YOLOv5改进 | 注意力机制 | 添加双重注意力机制 DoubleAttention【附代码/涨点能手】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 在图像识别中&#xff0c;学习捕捉长距离关系是基础。现有的CNN模型通常通过增加深度来建立这种关系&#xff0c;但这种形式效率极低。因此&…