Cesium 介绍之 点位弹框实现(可随地图移动)

945 阅读1分钟

Cesium 介绍之 点位弹框实现(可随地图移动)

点位弹框

openlayer中对点位弹框进行了封装,可以用 ol.Overlay 组件来实现,实现相对方便。但在Cesium中不存在该类,需要手动实现该功能。

export default{
    mounted(){
        this.addRenderListener(viewer);
    },
    methods:{
        // 重新开启点位弹框视图
        startShowDialog() {
            // 点位弹框是否可视
            if (this.visible) {
                // cartesian 笛卡尔坐标——用于地图移动时重新计算点位弹框所在屏幕位置,打开下一次弹框时需要记录上一次的屏幕坐标位置
                const { x, y } = SceneTransforms.wgs84ToWindowCoordinates(window.cesiumViewer.scene, this.cartesian);
                if (x && y) {
                    // 重新设置点位弹框的位置
                } else {
                    // 关闭弹框
                }
            }
        },
        // preRender——在场景更新后以及渲染场景之前触发
        addRenderListener(viewer) {
            viewer.scene.preRender.addEventListener(this.startShowDialog);
        },
          // 根据gps信息获取屏幕坐标 —— 用于点位弹框
        getScreenCoordinate(gpsX, gpsY, curPosition) {
            const pick = curPosition ? window.cesiumViewer.scene.pick(curPosition) : null;
            if (pick && pick.id) {
                // 根据cartographic获取实时高度
                const cartographic = Cartographic.fromCartesian(pick.primitive._actualPosition);
                const cartesian = Cartesian3.fromDegrees(gpsX, gpsY, cartographic.height);
                const position = SceneTransforms.wgs84ToWindowCoordinates(window.cesiumViewer.scene, cartesian);
                return { cartesian, position };
            } else {
                const cartesian = getPositionByGps(gpsX, gpsY);
                const position = SceneTransforms.wgs84ToWindowCoordinates(window.cesiumViewer.scene, cartesian);
                return { cartesian, position };
            }
        }
    }
}

编写点位弹框组件(popup.vue)、需要对外部cesium-popup设置定位position:fixed

// 点位弹框外框架对弹框内容进行插槽
<template>
    <div
        ref="cesiumPopup"
        class="cesium-popup"
        :style="{
            width: popupWidth + 'px',
            left: position.x + 'px',
            top: position.y + 'px'
        }"
    >
        <slot />
    </div>
</template>

export default{
    watch:{
        // 监听屏幕坐标变化,改变点位弹框位置
        coordinate(v) {
            this.handlePosition(v);
        }
    },
    methods:{
        async handlePosition(coordinate) {
            await this.$nextTick();
            const { offsetWidth, offsetHeight } = this.$refs.cesiumPopup;
            const diffW = offsetWidth - this.tempWidth;
            const diffH = offsetHeight - this.tempHeight;
            if (Math.abs(diffH) > 1 || Math.abs(diffW) > 1) {
                this.tempWidth = offsetWidth;
                this.tempHeight = offsetHeight;
            }
            if (Array.isArray(coordinate) && coordinate.length) {
                const [gpsX, gpsY] = coordinate;
                this.position = {
                    x: gpsX - this.tempWidth / 2 + this.pOffset[0],
                    y: gpsY - this.tempHeight + this.pOffset[1]
                };
            }
        }
    }
}