先看效果,弹窗会跟随实体移动
1、首先我们先写一个弹窗样式,如果是vue开发,css最好写到公共引入的css ,组件内css会编译后会加hash值
2、然后我们 开启 cesium的监听事件, 注意的是 initBubbleWindow方法在地球加载后再调用
const initBubbleWindow = () => {
let scene = viewer.scene,
camera = viewer.camera,
handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction((movement) => {
if (viewer.selectedEntity) {
// 获取实体id 如果是不同实体 可以在这里过滤
let selectID = viewer.selectedEntity.id
console.log(selectID)
// 创建弹窗前先关闭 之前的弹窗 如果你要展示多个弹窗 这里可以不用调用
orb.deletePopup()
orb.popupWindow(selectID);
} else {
// 如果你点的不是实体 是空白区域 弹窗销毁 如果你有统一销毁的方法 这里也可以省略
orb.deletePopup()
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK); // 监听左键
};
3、通过左键获取到 实体id后 我们拿到实体的数据,然后进行显示
// 气泡弹窗
popupWindow(id) {
// 先创建元素
let domId = "popupwin-" + id // 多个弹窗id不一样
let html = window.document.createElement("div");
html.className = "popupwin"; // 这里就是我们一开始写样式的弹窗
html.id = domId
document.body.appendChild(html);
let scene, camera
let helper = new window.Cesium.EventHelper();
let that = this
// 这里写一个函数 用cesium的计时器 定时调用,这也是 弹窗可以跟着实体移动的主要方式
function listenersfunc() {
scene = viewer.scene;
camera = viewer.camera;
if (
viewer.entities &&
viewer.entities.getById(id)
) {
// 根据实体id获取实体id的位置坐标
let cartesian = viewer.entities.getById(id)
.position.getValue(viewer.clock.currentTime)
// 三维转屏幕坐标 这里获取实体在屏幕中的位置
var px_position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
scene,
cartesian
)
// 这里转换成经纬高
let POS = window.Cesium.Cartographic.fromCartesian(cartesian)
// 获取弹窗 然后实时修改弹窗位置
let popDom = document.getElementById(domId)
var popw = popDom.offsetWidth;
var poph = popDom.offsetHeight;
popDom.style.top = px_position.y - poph + "px";
popDom.style.left = px_position.x - popw / 2 + "px";
// 这里添加弹窗内容,也是实时变化的
let infoHTML = '<p>经度:' + Number((POS.longitude * 180 / Math.PI)).toFixed(4) + '(°)</p>' +
'<p>纬度:' + Number((POS.latitude * 180 / Math.PI)).toFixed(4) + '(°)</p>' +
'<p>高度:' + Number((POS.height)).toFixed(4) + '(m)</p>'
popDom.innerHTML = infoHTML
}
}
// 把修改实体弹窗的函数添加的定时器里,进行循环调用
listenersfunc.prototype.id = id
let a = helper.add(viewer.clock.onTick, listenersfunc)
}
4、最好我们点击空白销毁弹窗
deletePopup(){
// 找出所有的定时器 找的名称是 listenersfunc 的移除
let AllListeners = window.viewer.clock.onTick._listeners;
AllListeners.map(value => {
if (value.name == "listenersfunc") {
window.viewer.clock.onTick.removeEventListener(value)
}
})
// 最好清除所以窗口 也可以根据id清除 ,因为我这里展示的是一个 所以用的 class
document.querySelector(".popupwin")?.remove()
最后就完成了