核心是获取鼠标点击位置的屏幕坐标,转换为空间坐标,再根据空间坐标计算实时的屏幕坐标。
绘制好弹窗之后,根据实时的屏幕坐标更新弹窗位置。
方便起见,封装了一个类,js文件如下。
其中destroy方法可以将弹窗销毁。
let Cesium = require("cesium/Cesium");
// let viewer=window.viewer
// 为传入的点生成InfoWindow
class InfoWindow{
position=undefined;
info;
infoWindow_postRender;
constructor(position){
console.log(position)
// Cartesian3
let viewer=window.viewer
this.position=position
this._initInfoWindowHTML()
this.info.style.position="absolute"
// info.style.left=
this.infoWindow_postRender=()=>{
// 空间坐标转屏幕坐标
let canvas=viewer.scene.cartesianToCanvasCoordinates(this.position)
this.info.style.left=(canvas.x-270)+'px'
this.info.style.bottom=(window.innerHeight-canvas.y+10)+'px'
}
viewer.scene.postRender.addEventListener(this.infoWindow_postRender)
}
// 屏幕坐标-》空间坐标-》实时的屏幕坐标
_initInfoWindowHTML(){
let info=document.createElement('div')
info.innerHTML=`
<div class="infoWindow-header">
坐标
</div>
<div class="infoWindow-body">
<ul>
<li>
笛卡尔坐标 x:${Number(this.position.x).toFixed(6)},y:${Number(this.position.y).toFixed(6)},z:${Number(this.position.z).toFixed(6)}
</li>
</ul>
</div>
<div class="infoWindow-bottom">
<div class="arrow"></div>
</div>
`
// info.setAttribute('id','infoWindow')
info.setAttribute('class','infoWindow-show')
this.info=info
info.style.position="absolute"
info.style.width="500px"
document.getElementById('container').append(info)
}
destroy(){
// 销毁当前infoWindow
let viewer=window.viewer
// 清除监听事件
viewer.scene.postRender.removeEventListener(this.infoWindow_postRender)
// 清除dom
this.info.remove()
}
}
export default InfoWindow;
css样式
.infoWindow-show{
background-color: #fff;
box-shadow: 2px 2px 20px rgba(100,100,100,0.5);
/* width: 400px;
height: 300px; */
z-index: 9999;
display: block;
text-align: center;
padding: 20px;
padding-bottom: 0;
}
.infoWindow-header{
line-height: 80px;
height: 80px;
font-size: 20px;
color:#000;
}
.infoWindow-bottom{
position: relative;
}
.infoWindow-bottom .arrow{
position: absolute;
left: 50%;
top:0;
transform: translate(-50%,0);
width: 0;
height: 0;
border-width: 10px;
border-style: solid;
border-color: #fff transparent transparent transparent;
}
调用:这里是直接获取点位的坐标(scene.pickPosition);如果存在feature,用scene.pick进行拾取,可以拿到feature的一些属性信息,就可以针对点击的feature生成信息弹窗辣。
<template>
<div id="container">
<div class="define-tool">
<tool></tool>
</div>
<div id="cesium-app"></div>
</div>
</template>
addInfoWindow(){
// 在点击处生成弹窗
let Cesium=window.Cesium
let viewer=window.viewer
let infoWindow_leftClickHandler=new Cesium.ScreenSpaceEventHandler()
let infoWindow
infoWindow_leftClickHandler.setInputAction((e)=>{
// // console.log(e)
// scene.pick返回点击处的feature
// let position= viewer.scene.pick(e.position)
// scene.pickPosition返回空间坐标 拾取地图外的点将返回undefined
if(infoWindow){
infoWindow.destroy()
}
let position=viewer.scene.pickPosition(e.position)
if(position){
infoWindow=new InfoWindow(position)
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
},