文章目录

  • 前言
  • 基本思路
  • 代码
  • 总结

前言

在Cesium中没有类似mapbox中的气泡(popup)弹框,在react-hooks中可以封装一个这样的类组件,思路参考来源,在此基础上进行了改进,实现为外部模型添加popup气泡框,在旋转缩放时仍能保持原位置,不会偏移。


基本思路

  • 为地图绑定鼠标事件,当拾取到模型时,触发响应函数
  • 将鼠标点击位置的屏幕坐标转为笛卡尔坐标,与拾取到的目标模型要素的属性一起传递给popup组件,创建构造函数,触发构造popup类
  • 在popup类初始化时,创建div,显示气泡框,同时在该类内部添加每一帧的监听函数,将传递来的笛卡尔坐标转为屏幕坐标,重新设置气泡框位置
  • 创建新的气泡框或者关闭气泡框时,移除div元素,解绑监听事件

代码

贴两部分的代码,popup工具类的声明和在主程序中的使用。

import * as Cesium from "cesium";
import './index.css'interface InfoProrety {name: string,viewer: Cesium.Viewer,properties: PropertyObj,geometry: Cesium.Cartesian3
}interface PropertyObj {[key: string]: string | number;// important: string;// other: string;
}class Popup {id: numberviewer: Cesium.Viewergeometry: Cesium.Cartesian3ctn: HTMLDivElementeventListener: anyconstructor(info: InfoProrety) {console.log(info)this.id = 0;// 展示新的popup时关闭前一个popupif (document.getElementsByClassName("bx-popup-ctn").length > 0) {console.log(document.getElementsByClassName("bx-popup-ctn"))document.getElementsByClassName("bx-popup-ctn")[0].remove()}this.viewer = info.viewer; // 弹窗创建的viewerthis.geometry = info.geometry; // 弹窗挂载的位置this.ctn = document.createElement("div"); // 创建一个div// classList为html5的新语法,返回元素类名this.ctn.classList.add("bx-popup-ctn");this.viewer.container.append(this.ctn);  // Cesium.Viewer.container 获取当前viewer的父容器(cesiumContainer)this.ctn.innerHTML = this.createHtml(info.name, info.properties); //创建Htmlthis.render(this.geometry);// 添加监听拖动重新渲染位置 viewer.clock.onTick时刻监听this.eventListener = this.viewer.clock.onTick.addEventListener(clock => {this.render(this.geometry);});// 关闭按钮绑定关闭事件document.getElementsByClassName("popup-close-button"// @ts-ignore)[0].onclick = () => {this.close();};}//渲染位置render(geometry: Cesium.Cartesian3) {const position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene,geometry);if (position) {this.ctn.style.left = position.x - this.ctn.offsetWidth / 2 + "px";this.ctn.style.top = position.y - this.ctn.offsetHeight - 30 + "px";}}createHtml(header: string, content: PropertyObj) {var html ='<div class="bx-popup-header-ctn">' +header +'<span class="popup-close-button" >' + "❌" + '</i></span>' +"</div>" +'<div class="bx-popup-content-ctn" >' +'<div class="bx-popup-content" >' +this.createTable(content) +"</div>" +"</div>" +'<div class="bx-popup-tip-container" >' +'<div class="bx-popup-tip" >' +"</div>" +"</div>";return html;}createTable(content: PropertyObj) {let html = '<table class="table-popup">';for (let key in content) {html += `<tr><td class="title-popup">${key}</td><td class="value-popup">${content[key]}</td></tr>`;}html += "</table>";return html;}close() {this.ctn.remove();this.viewer.clock.onTick.removeEventListener(this.eventListener);}
}
export default Popup;

引用部分,只保留相关部分。

  const handleChange = (value: string, option: any) => {console.log(`selected ${value}`, option);const handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)if (value === 'popup') {// 添加鼠标事件:右键handler.setInputAction(function (movement:any) { // 鼠标点击是PositionedEvent类型 :{ position }// pick方法返回primitive对象,当对象为3d tiles时,返回Cesium3DTileFeature对象const feature = viewer!.scene.pick(movement.position);const point = new Cesium.Cartesian2(movement.position.x,movement.position.y)if (feature instanceof Cesium.Cesium3DTileFeature) {displaySelectFeature(feature, point)}}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);}};const displaySelectFeature = (feature: Cesium.Cesium3DTileFeature, point: Cesium.Cartesian2) => {if (!Cesium.defined(feature)) {return;}// 获取当前鼠标位置三维坐标的一般流程(无模型):// 1:通过camera的getPickRay,将当前的屏幕坐标转为ray(射线)=> viewer.camera.getPickRay(windowCoordinates);// 2:找出ray和地形的交点,得出三维世界坐标 scene.globe.pick(ray, scene);// 获取当前鼠标位置三维坐标的一般流程(有模型):// viewer!.scene.pickPosition(Cartesian2)let propertyObj: PropertyObj = {} // 存储到对象中const propertyIds = feature.getPropertyIds()propertyIds.length && propertyIds.forEach(item => {propertyObj[item] = feature.getProperty(item)});// @ts-ignorePopupRef.current = new Popup({name: 'xxx',viewer: viewer!,properties: propertyObj,geometry:viewer!.scene.pickPosition(point)});}

总结

借助网上的思路实现的一个popup功能,核心的部分其实两篇来源中都已经实现了,修正了下存在的问题。

Cesium为3dTile模型添加气泡框相关推荐

  1. Arc Engine 中添加气泡提示框

    一.在ArcMap中的定位操作 已知若干点的经纬度坐标,要求在地图中进行定位: 1.通过Tool >Add X Y data 定位点,注意选择地理坐标系下的wgs 1984坐标系: 2.定位后的 ...

  2. linux视频对话框,抖音对话框视频怎么做?如何在视频画面上添加对话气泡框?视频加对话气泡的方法...

    小编家里有个快要两周岁的小侄女,平日里总是喜欢做一些人小鬼大的事情,这不,前段时间她妈妈发了一个小视频,她拉着一个跟她差不多大的行李箱一脸严肃地说她要去上班~那么小一个小不点,居然很认真地对她妈妈说要 ...

  3. android高德地图气泡,[置顶] Android-高德地图-显示气泡框

    现在的聊天框大多都是气泡框,气泡框长相可爱,有良好的用户体验. 如何把气泡框应用于地图上呢? 步骤一:首先要定义我们的气泡框布局,也就是所谓的layout. popup.xml: android:ba ...

  4. Matlab - Solidworks 机器人建模(5)—— 给模型添加摩擦力

    Matlab - Solidworks 机器人建模(5)-- 给模型添加摩擦力 0. 前言 建好模型并成功进行一次仿真之后,我们发现虽然模型可以像模像样的产生由重力带来的运动,但是也发现零件可以穿过其 ...

  5. html怎么制作气泡,制作CSS气泡框

    气泡状文本框,是一种很生动的网页设计手段. 它可以用来表示用户的发言. 也可以用来作为特定信息的提示符. DVD租借网站Netflix,还用它显示碟片的详细信息. ================== ...

  6. vue 使用 cesium 接入 gltf 模型

    vue 使用 cesium 接入 gltf 模型 这个其实说简单也简单,但是说复杂也不容易搞.尤其是转化成vue语法或者是在vue项目接入的时候会有些许的坑,我在接入的时候也是有很多问题,好在最后把模 ...

  7. Cesium加载模型两种方式

    Cesium加载模型两种方式 代码如下 <!DOCTYPE html> <html><head><meta charset="UTF-8" ...

  8. 在vue页面中使用伪元素进行 气泡框创建|选中效果自定义|滚动条自定义

    在vue页面中使用伪元素进行 气泡框|单选框自定义|滚动条自定义 1. 基于vue,使用到的图标是element plus 2. vue单页面代码 <template><h1> ...

  9. cesium实现向卫星添加传感器并跟随卫星移动

    cesium实现向卫星添加传感器并跟随卫星移动 import * as Cesium from 'cesium' import "./CesiumSensors.js";/* es ...

  10. 高德地图关闭气泡高德android,Android-高德地图-显示气泡框

    现在的聊天框大多都是气泡框,气泡框长相可爱,有良好的用户体验. 如何把气泡框应用于地图上呢? 步骤一:首先要定义我们的气泡框布局,也就是所谓的layout. popup.xml: android:ba ...

最新文章

  1. response.setContentType()方法浅析
  2. function里面可以写function吗_和田玉不戴的时候,可以长时间泡在水里面吗?
  3. 二维粗糙海面matlab,三维随机粗糙海面的Monte-Carlo仿真
  4. 微信独立精彩互换抢红包系统源码ThinkPHP开源版
  5. Linux中的atim、mtime、ctime
  6. Java后端实现视频分段渐进式播放
  7. 【算法篇】汉诺塔问题
  8. 用PPO玩2048游戏--可以达到合成2048的目的
  9. 流行和声(5)minor7和弦
  10. What kind of new area will CFun and creation form?
  11. 【软件质量】问题与保证谈论
  12. 校招和社招有什么区别?不同时期重点不同!
  13. KPM算法思想及实现
  14. matlab字体安装,matlab安装教程
  15. 怎么修改原图片的尺寸?图片尺寸在线修改工具分享
  16. 2018年全国心理测试技术研究、应用及专业人员培养研讨会活动简报
  17. 计算一个数字的长度的几种方法
  18. Linux安全培训 ppt,腾讯内部培训资料linux安全基础ppt课件
  19. 万智牌天使恩典oracle,万智牌:每日套牌搬运 twitch 今日直播牌组
  20. 使用matlab编写人脸识别的程序,并制作UI界面

热门文章

  1. OVNOVS代码下载、编译安装以及运行步骤
  2. PHP通过地址获取经纬度
  3. 【项目实战】——历史数据归档
  4. GitHub新手使用教学(从安装到使用)
  5. 腾讯下载的qlv格式视频转换mp4格式方法
  6. 代码统计工具 cloc 和 scc
  7. 华为qq邮箱服务器密码忘了,华为手机qq邮箱无法登录电子邮件鉴权失败的解决办法...
  8. pygame 入门实例教程 1 - 复古方块赛车游戏
  9. mongodb 副本集Replica Set的keyfile验证
  10. [C#] RSA 加密解密