显示点位图标
export default class DragEntity {
constructor(val) {
this.viewer = val.viewer
}
addEntity(value) {
let pinBuilder = new Cesium.PinBuilder();
const url = Cesium.buildModuleUrl(value.text);
let poin = Promise.resolve(
pinBuilder.fromUrl(url, Cesium.Color[value.color]||value.color, 48)
).then((canvas) => {
return this.viewer.entities.add({
id: value.id,
name: value.type,
position: Cesium.Cartesian3.fromDegrees(value.position.x, value.position.y),
billboard: {
image: canvas.toDataURL(),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
monitoItems: {
data: value
},
});
});
return poin
}
}
创建用于显示弹框的封装
import Vue from "vue";
import Label from "./index.vue";
let WindowVm = Vue.extend(Label);
export default class Bubble {
constructor(val) {
this.viewer = val.viewer;
let lon = val?.longitude
let lat = val?.latitude
let position = {lon,lat}
this.position = val?.position||position;
this.vmInstance = new WindowVm({
propsData: {
value: val?._monitoItems?.data || {}
}
}).$mount();
this.vmInstance.closeEvent = e => {
this.windowClose();
}
val.viewer.cesiumWidget.container.appendChild(this.vmInstance.$el);
this.addPostRender();
}
addPostRender() {
this.viewer.scene.postRender.addEventListener(this.postRender, this);
}
postRender() {
if (!this.vmInstance.$el || !this.vmInstance.$el.style) return;
const canvasHeight = this.viewer.scene.canvas.height;
const windowPosition = new Cesium.Cartesian2();
Cesium.SceneTransforms.wgs84ToWindowCoordinates(
this.viewer.scene,
this.position,
windowPosition
);
this.vmInstance.$el.style.bottom =
canvasHeight - windowPosition.y + 240 + "px";
const elWidth = this.vmInstance.$el.offsetWidth;
this.vmInstance.$el.style.left = windowPosition.x - elWidth / 2 + 600 + "px";
const camerPosition = this.viewer.camera.position;
let height = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(camerPosition).height;
height += this.viewer.scene.globe.ellipsoid.maximumRadius;
}
windowClose() {
if (this.vmInstance) {
this.vmInstance.$el.remove();
this.vmInstance.$destroy();
}
if (!this.vmInstance.$el || !this.vmInstance.$el.style) {
return
}else{
this.vmInstance.$el.style.display = "none";
this.viewer.scene.postRender.removeEventListener(this.postRender, this);
};
}
}
创建用于显示弹框的vue文件
<template>
<div :id="value.id">
<div class="box-wrap">
<div class="close" @click="closeClick">X</div>
<div class="area">
<el-tooltip class="item" effect="dark" :content="value.name ||'暂无信息'" placement="top">
<div class="area-title fontColor text_show" style="padding-left:26px">{{ value.name || "暂无信息" }}</div>
</el-tooltip>
</div>
<div class="content" v-if="value.type == 'patrol'">
<div class="data-li" style="width: 120px">
<div class="data-label textColor">人员状态:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ value.state }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前经度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.position.y).toFixed(3) }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前纬度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.position.x).toFixed(3) }}</span>
</div>
</div>
</div>
<div class="content" v-if="value.type == 'building'">
<div class="data-li" :style="{ width: textW }">
<div class="data-label textColor">识别类型:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ value.state || "疑似超障" }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前经度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.position.y).toFixed(3) }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前纬度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.position.x).toFixed(3) }}</span>
</div>
</div>
</div>
<div class="content" v-if="value.buildingType&&value.createTime">
<div class="data-li">
<div class="data-label textColor">录入时间:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ value.createTime.split('T')[0] || "暂无信息" }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">建筑高度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{setModelHeight(value)}}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前经度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.longitude).toFixed(3) }}</span>
</div>
</div>
<div class="data-li">
<div class="data-label textColor">当前纬度:</div>
<div class="data-value">
<span class="label-num yellowColor">{{ Number(value.latitude).toFixed(3) }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import getMinHeight from './getMinHeight.js'
export default {
name: "DynamicLabel",
data() {
return {
show: true,
runway:{
runway1:'跑道RWY04/22',
},
elevationalAll:{},
elevationalShow:false,
};
},
props: {
value: {
type: Object,
default: {}
}
},
methods: {
closeClick() {
if (this.closeEvent) {
this.closeEvent();
this.removePoint()
}
},
removePoint() {
if (window.point.length > 0) {
window.point.forEach((c) => {
viewer.entities.remove(c);
});
}
},
},
computed: {
textW() {
return this.value.name?(this.value.name.split("").length * 22) + "px": 10 *22 +"px"
}
}
};
</script>
<style lang="less" scoped>
.detali-text{
color: #00fcff;
text-align: center;
font-size: 17px;
font-weight: 600;
animation: fontColor 1s;
}
.detali-text:hover{
cursor: pointer;
}
.flex{
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.box_1 {
position: relative;
bottom: 0;
left: 0;
}
.close {
position: absolute;
color: #fff;
top: 1px;
right: 10px;
text-shadow: 2px 2px 2px #022122;
cursor: pointer;
animation: fontColor 1s;
}
.box-wrap {
position: absolute;
left: 21%;
top: 0;
min-width: 300px;
border-radius: 50px 0px 50px 0px;
border: 1px solid #38e1ff;
background-color: #38e1ff4a;
box-shadow: 0 0 10px 2px #29baf1;
animation: slide 2s;
}
.box-wrap .area {
position: absolute;
top: 20px;
right: 0;
width: 95%;
height: 30px;
background-image: linear-gradient(to left, #4cdef9, #4cdef96b);
border-radius: 30px 0px 0px 0px;
animation: area 1s;
}
.pine {
position: absolute;
left: 0;
bottom: -83px;
width: 100px;
height: 100px;
box-sizing: border-box;
line-height: 120px;
text-indent: 5px;
}
.area .area-title {
text-align: center;
line-height: 30px;
white-space: nowrap;
}
.textColor {
font-size: 16px;
font-weight: 600;
color: #ffffff;
text-shadow: 1px 1px 5px #002520d2;
animation: fontColor 1s;
letter-spacing: 2px;
word-spacing: 2px;
}
.yellowColor {
font-size: 16px;
font-weight: 600;
color: #00fcff;
text-shadow: 1px 1px 5px #002520d2;
animation: fontColor 1s;
letter-spacing: 2px;
word-spacing: 2px;
}
.fontColor {
font-size: 16px;
font-weight: 800;
color: #ffffff;
text-shadow: 1px 1px 5px #002520d2;
animation: fontColor 1s;
letter-spacing: 2px;
word-spacing: 2px;
}
.content {
padding: 55px 10px 10px 10px;
}
.content .data-li {
}
.elevational-item{
padding-right: 8px;
display: inline-block;
}
.text_show{
overflow: hidden;
text-overflow: ellipsis;
}
@keyframes fontColor {
0% {
color: #ffffff00;
text-shadow: 1px 1px 5px #00252000;
}
40% {
color: #ffffff00;
text-shadow: 1px 1px 5px #00252000;
}
100% {
color: #ffffff;
text-shadow: 1px 1px 5px #002520d2;
}
}
@keyframes slide {
0% {
border: 1px solid #38e1ff00;
background-color: #38e1ff00;
box-shadow: 0 0 10px 2px #29baf100;
}
100% {
border: 1px solid #38e1ff;
background-color: #38e1ff4a;
box-shadow: 0 0 10px 2px #29baf1;
}
}
@keyframes area {
0% {
width: 0%;
}
25% {
width: 0%;
}
100% {
width: 95%;
}
}
@keyframes slash {
0% {
transform: rotateZ(135deg) scale(0);
}
100% {
transform: rotateZ(135deg) scale(1.5);
}
}
</style>