cesium实现自定义弹窗(随地球移动)vue3+cesium

1,200 阅读1分钟

完成的效果

image.png

第一步添加地图点击事件(我是在onMounted中定义的)
 
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.value.scene.canvas)
    handler.setInputAction((e) => {
 
         判断有没有地图的这个属性
        if (!viewer.value.scene) return
        
        let data = viewer.value.scene.pick(e.position)
        let { id } = data
           
        获取到数据返回的经纬度 
        let location = id.monitoItems.data.location.split(',')
 
        形成可以使用的px位置
        let cartesian = Cesium.Cartesian3.fromDegrees(Number(location[0]), Number(location[1]), 0)
     
        positionXy.xAxis = e.position.x - 100
        positionXy.yAxis = e.position.y - 100
 
        打开弹框
        proxy.$refs['popInfoRef'].openInfo()
 
        //实时更新位置 这个很重要 不然弹框会固定在屏幕的一个位置不随地图转动
        viewer.value.scene.postRender.addEventListener(() => {
            let windowPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.value.scene, cartesian)
            positionXy.xAxis = windowPosition.x - 100
            positionXy.yAxis = windowPosition.y - 100
        })
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
第二步 先自定义一个弹框的样式(vue3)

最重要的是 动态传入的 left和top 根据点击的位置实时更新弹框出现的位置。

<template>
这里的 positionXy.xAxis、positionXy.yAxis 是动态传入的 
        <div v-show="infoShow" class="content_info" :style="{
                left: positionXy.xAxis + 'px',
                top: positionXy.yAxis + 'px'
        }">
 
 
                <div @click="closeBtn" class="close_btn"><el-icon>
                                <Close />
                        </el-icon></div>
                <div class="title"> 名称: <span class="title_content">{{ positionXy.monitoItems.name }}</span> </div>
                <div class="title"> 地址:<span class="title_content">{{ positionXy.monitoItems.cityname +
                        positionXy.monitoItems.adname +
                        positionXy.monitoItems.address
                }}</span> </div>
 
                <div class="info_triangle">
 
 
                </div>
 
        </div>
</template>
 
<script setup>
 
let infoShow = ref(false)
const props = defineProps({
        positionXy: {
                type: Object,
                default: {}
        }
})
function closeBtn() {
        infoShow.value = false
}
 
function openInfo() {
        infoShow.value = true
}
defineExpose({
        openInfo, closeBtn
})
</script>
 
<style lang="scss" scoped>
.content_info {
        border-radius: 3px;
        box-shadow: 0 1px 2px rgba(0, 0, 0, .1);
        padding: 10px 10px 15px;
        position: absolute;
        background-color: #fff;
        // height: 20px;
        width: 200px;
        z-index: 999999;
        font-size: 12px;
 
        .close_btn {
                position: absolute;
                top: 2px;
                right: 2px;
        }
 
        .title {
                font-size: 12px;
                font-weight: 700;
                // transform: scale(.8);
 
                .title_content {
                        font-size: 12;
                        // transform: scale(.8);
                        font-weight: normal;
                        color: #555555;
                }
        }
}
 
.info_triangle {
        width: 0;
        height: 0;
        border: 15px solid;
        border-color: #fff transparent transparent transparent;
        position: absolute;
        left: 50%;
        bottom: -29px;
        transform: translateX(-50%);
 
 
}
</style>

以上就是点击屏幕显示弹框信息的所有内容