cesium3DTiles + Antd + React 实现自定义弹窗
项目需求中有一个鼠标滑过地图标记点展示自定义信息,百度了有好多种写法,但是都应用不到我自己这里,于是自己想了一个办法,算是变相完成,简单的说一下思路,就是如果想要用antd里面的popover就要用Popover嵌套一个元素,当鼠标滑过这个元素弹窗就是展示,由于cesium是一整个canvas图,我想到的就是将你标记点的经纬度转换为屏幕坐标(转换方法cesium已经给出),然后写一个单独的盒子外面套上Popover,再将这个盒子定位到上面转换
我这里使用的是antd里面的Popover组件,其他组件库不确定是不是这样的,elementUi的使用方法是跟这个一样的,应该也可以生效,直接看代码,初始化那些代码就不粘贴出来了,这些都是建立在你可以初始化3d地图并且可以画出标记点的前提下
代码中有几个注意的点是
1、popover包裹的盒子要大小适中,最好刚刚能包裹住你的标记点
2、要添加绝对定位属性position:‘absolute’
3、盒子设置成透明的
4、鼠标移动到想要的点后盒子的display属性设置成’block’否则设置成’none’
5、盒子的z-index值必须很大就像代码中写的999那样就可以
一、第一部分代码是Popover,你可以把它放到跟cesium盒子同级
<div id={'cesiumContainer'} style={{width: '100%',height: '100%',position: "relative",}}></div> //3d地图容器
//Popover
<Popover
content={
<div>
<p>Content</p>
<p>Content</p>
</div>
}>
<div id={'popoverBox'} style={{width: 70, height: 70, position: "absolute", zIndex: 9999, opacity: 0}}></div>
</Popover>
二、第二部分代码是鼠标滑动事件
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
if (viewer.scene.mode !== Cesium.SceneMode.MORPHING) {
let pick = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(pick) && (pick.id && pick.id.id)) {
let popBox= document.getElementById("popoverBox"); //这个是Popover包裹的盒子
if (pick.id.id.split('_')[1] == 'waterQuality') {//这里是判断鼠标是否滑动到了你想要的标记点上,判断条件因代码而异
//设置弹出框位置
let winpos = viewer.scene.cartesianToCanvasCoordinates(
pick.id.position._value
); //这里拿到你的标记点的坐标转换成屏幕坐标用来定位你的Popover包裹的盒子
popBox.style.display = 'block';
popBox.style.left = winpos.x + "px";
popBox.style.top = winpos.y - 36 + "px"; //根据你标记点的位置调整下,使你的标记点刚好被盒子包裹住
trackPop = pick.id.position._value;
} else {
//如果鼠标没有滑动到你想要的标记点盒子是透明的
popBox.style.display= 'none';
}
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
可以看到盒子刚好可以盖住你的标记点,这样就达到的Popover包裹盒子的目的