Cesium为3dTile模型添加气泡框
文章目录
- 前言
- 基本思路
- 代码
- 总结
前言
在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模型添加气泡框相关推荐
- Arc Engine 中添加气泡提示框
一.在ArcMap中的定位操作 已知若干点的经纬度坐标,要求在地图中进行定位: 1.通过Tool >Add X Y data 定位点,注意选择地理坐标系下的wgs 1984坐标系: 2.定位后的 ...
- linux视频对话框,抖音对话框视频怎么做?如何在视频画面上添加对话气泡框?视频加对话气泡的方法...
小编家里有个快要两周岁的小侄女,平日里总是喜欢做一些人小鬼大的事情,这不,前段时间她妈妈发了一个小视频,她拉着一个跟她差不多大的行李箱一脸严肃地说她要去上班~那么小一个小不点,居然很认真地对她妈妈说要 ...
- android高德地图气泡,[置顶] Android-高德地图-显示气泡框
现在的聊天框大多都是气泡框,气泡框长相可爱,有良好的用户体验. 如何把气泡框应用于地图上呢? 步骤一:首先要定义我们的气泡框布局,也就是所谓的layout. popup.xml: android:ba ...
- Matlab - Solidworks 机器人建模(5)—— 给模型添加摩擦力
Matlab - Solidworks 机器人建模(5)-- 给模型添加摩擦力 0. 前言 建好模型并成功进行一次仿真之后,我们发现虽然模型可以像模像样的产生由重力带来的运动,但是也发现零件可以穿过其 ...
- html怎么制作气泡,制作CSS气泡框
气泡状文本框,是一种很生动的网页设计手段. 它可以用来表示用户的发言. 也可以用来作为特定信息的提示符. DVD租借网站Netflix,还用它显示碟片的详细信息. ================== ...
- vue 使用 cesium 接入 gltf 模型
vue 使用 cesium 接入 gltf 模型 这个其实说简单也简单,但是说复杂也不容易搞.尤其是转化成vue语法或者是在vue项目接入的时候会有些许的坑,我在接入的时候也是有很多问题,好在最后把模 ...
- Cesium加载模型两种方式
Cesium加载模型两种方式 代码如下 <!DOCTYPE html> <html><head><meta charset="UTF-8" ...
- 在vue页面中使用伪元素进行 气泡框创建|选中效果自定义|滚动条自定义
在vue页面中使用伪元素进行 气泡框|单选框自定义|滚动条自定义 1. 基于vue,使用到的图标是element plus 2. vue单页面代码 <template><h1> ...
- cesium实现向卫星添加传感器并跟随卫星移动
cesium实现向卫星添加传感器并跟随卫星移动 import * as Cesium from 'cesium' import "./CesiumSensors.js";/* es ...
- 高德地图关闭气泡高德android,Android-高德地图-显示气泡框
现在的聊天框大多都是气泡框,气泡框长相可爱,有良好的用户体验. 如何把气泡框应用于地图上呢? 步骤一:首先要定义我们的气泡框布局,也就是所谓的layout. popup.xml: android:ba ...
最新文章
- response.setContentType()方法浅析
- function里面可以写function吗_和田玉不戴的时候,可以长时间泡在水里面吗?
- 二维粗糙海面matlab,三维随机粗糙海面的Monte-Carlo仿真
- 微信独立精彩互换抢红包系统源码ThinkPHP开源版
- Linux中的atim、mtime、ctime
- Java后端实现视频分段渐进式播放
- 【算法篇】汉诺塔问题
- 用PPO玩2048游戏--可以达到合成2048的目的
- 流行和声(5)minor7和弦
- What kind of new area will CFun and creation form?
- 【软件质量】问题与保证谈论
- 校招和社招有什么区别?不同时期重点不同!
- KPM算法思想及实现
- matlab字体安装,matlab安装教程
- 怎么修改原图片的尺寸?图片尺寸在线修改工具分享
- 2018年全国心理测试技术研究、应用及专业人员培养研讨会活动简报
- 计算一个数字的长度的几种方法
- Linux安全培训 ppt,腾讯内部培训资料linux安全基础ppt课件
- 万智牌天使恩典oracle,万智牌:每日套牌搬运 twitch 今日直播牌组
- 使用matlab编写人脸识别的程序,并制作UI界面