需求:
1.点击图标弹出弹框,点击弹框以外的地方或者弹框上面的“X”关闭弹窗
2.拖动或者放大缩小地图弹框跟随图标移动
3.地球翻转到另一面弹框关闭
效果图:
弹框组件代码(组件就在初始化地图视图里面的容器里面使用即可):
<template>
<div id="infoCard_" class="infoCard">
<div class="warninfo">
<div class="warnInfo_lable">
<div class="warnInfo_lable_">告警</div>
<div class="warnInfo_close" @click="()=>{setVisible(false);}"></div>
</div>
<div class="warnInfo_msg">
<div class="row">
<div class="lable">告警时间</div>
<div class="value">{{ warnInfo.eventtime }}</div>
</div>
<div class="row">
<div class="lable">告警类型</div>
<div class="value">{{ warnInfo.eventtype }}</div>
</div>
<div class="row">
<div class="lable">告警内容</div>
<div class="value">{{ warnInfo.datatype }}</div>
</div>
<div class="row">
<div class="lable">告警地点</div>
<div class="value">{{ warnInfo.device.fulladdress }}</div>
</div>
<div class="row">
<div class="lable">告警等级</div>
<div class="value">{{ warnInfo.device.level }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import * as Cesium from 'cesium';
export default {
name: 'EarthCard',
components: {},
props: {},
data() {
return {
Interval: null,
isInit: false,
addDiv: null,
click_point: null,
screenC: null,
isVisible: false,
removeHandler: null,
warnInfo: {
eventtime: "",
datatype: "",
eventtype: "",
device: {
level: "",
fulladdress: ""
}
},
}
},
computed: {},
watch: {},
mounted() {
this.Interval = setInterval(() => {
if (window.earth) {
clearInterval(this.Interval);
this.Interval = null;
//初始化弹窗div
this.initTool();
this.addLeftClick()
this.cameraMove()
}
}, 200)
},
methods: {
initTool() {
if (this.isInit) {
return 0;
}
this.addDiv = document.getElementById("infoCard_");
this.isInit = true;
},
//控制弹窗显隐
setVisible: function (visible) {
if (!this.isInit) {
return;
}
if (this.addDiv) {
this.addDiv.style.display = visible ? 'block' : 'none';
}
},
//控制弹窗定位
showAt: function (position) {
if (!this.isInit) {
return;
}
if (position) {
let height = window.innerHeight || document.body.clientHeight;
let ratio = height / 953;
this.setVisible(true);
if (this.addDiv) {
this.addDiv.style.left = position.x + (ratio * 10) + "px";
this.addDiv.style.top = position.y - (ratio * 230) + "px";
}
}
},
addLeftClick() {
//点击地图事件
const handler = new Cesium.ScreenSpaceEventHandler(earth.scene.canvas);
handler.setInputAction((event) => {
const pick = earth.scene.pick(event.position);
//选中某模型pick选中的对象
if (pick && pick.id) {
let entityID = pick.id._id;
//标识
let identifying = entityID.split("_")[0];
let myEntity = earth.entities.getById(entityID);
//点击告警图标触发
if (identifying === "warn") {
let Cartesian3 = Cesium.Cartesian3.fromDegrees(myEntity.myInfo.lon, myEntity.myInfo.lat, 0);
let canvasPosition = new Cesium.Cartesian2();
let position = earth.scene.cartesianToCanvasCoordinates(Cartesian3, canvasPosition)
this.screenC = new Cesium.Cartesian2(position.x, position.y);
this.click_point = Cesium.Cartesian3.fromDegrees(myEntity.myInfo.lon, myEntity.myInfo.lat);
this.warnInfo = myEntity.myInfo;
this.showAt(this.screenC);
}
} else {
this.setVisible(false);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
},
cameraMove() {
//相机移动开始事件
earth.scene.camera.moveStart.addEventListener(() => {
this.removeHandler = earth.scene.postRender.addEventListener(() => {
// console.log("相机离远了")
if (this.screenC) {
this.isVisible = new Cesium.EllipsoidalOccluder(Cesium.Ellipsoid.WGS84, earth.camera.position).isPointVisible(this.click_point);
if (this.isVisible === false) {
this.setVisible(false)
} else {
this.screenC = Cesium.SceneTransforms.wgs84ToWindowCoordinates(earth.scene, this.click_point);
if (this.addDiv.style.display === 'block') {
this.showAt(this.screenC)
}
}
}
})
})
//相机移动结束事件
earth.scene.camera.moveEnd.addEventListener(() => {
// console.log("相机靠近了")
if (this.removeHandler) {
this.removeHandler();
}
})
},
}
}
</script>
<style lang="less" scoped>
@ratio: calc(100vh / 953);
.infoCard {
z-index: 10;
position: absolute;
//pointer-events: none;
display: none;
.warninfo {
width: calc(@ratio * 370);
height: calc(@ratio * 200);
background-image: url("../image/PC/cockpit/warn_box.png");
background-size: 100% 100%;
overflow: hidden;
.warnInfo_lable {
width: 89%;
height: calc(@ratio * 35);
margin-left: calc(@ratio * 36);
position: relative;
//border: 1px solid blue;
display: flex;
justify-content: flex-start;
align-items: center;
.warnInfo_lable_ {
color: white;
margin-left: calc(@ratio * 5);
}
.warnInfo_close {
//border: 1px solid blue;
width: calc(@ratio * 16);
height: calc(@ratio * 16);
margin-left: auto;
margin-right: calc(@ratio * 7);
margin-bottom: calc(@ratio * -28);
z-index: 11;
}
}
.warnInfo_msg {
margin-top: calc(@ratio * 10);
width: 100%;
margin-left: calc(@ratio * 50);
.row {
height: 100%;
width: 100%;
display: flex;
margin-top: calc(@ratio * 6);
color: #FF7676;
font-size: calc(@ratio * 12);
background: linear-gradient(90deg, rgba(82, 71, 76, 0.00) 0%, rgba(104, 49, 53, 0.47) 46.35%, rgba(82, 71, 76, 0.00) 100%);
.lable {
height: 25%;
width: 20%;
overflow: hidden;
}
.value {
height: 25%;
width: 80%;
overflow: hidden;
color: #fff;
}
}
}
}
}
</style>
弹框组件中earth为初始化地图时创建的地图视图,如下图:
弹框组件中myInfo为创建触发点图标时自定义的属性,里面包含经纬度信息,附创建图标的代码:
//其中earth与弹框组件中的earth一样
drawIcon = function (item, id, visible) {
let myEntity = earth.entities.getById(id);
if (myEntity) {
myEntity.position = Cesium.Cartesian3.fromDegrees(item.lon, item.lat, 0);
myEntity.billboard.image = item.url;
myEntity.billboard.height = item.height;
myEntity.billboard.width = item.width;
return;
}
let icon = earth.entities.add({
position: Cesium.Cartesian3.fromDegrees(item.lon, item.lat, 0),
id: id,
myInfo: item,
billboard: {
// 图像地址,URI或Canvas的属性
image: item.url,
// 设置颜色和透明度
color: Cesium.Color.WHITE.withAlpha(1),
// 高度(以像素为单位)
height: item.height,
// 宽度(以像素为单位)
width: item.width,
// 相对于坐标的垂直位置
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// 是否显示
show: visible,
}
})
}