Cesium mouse prompt function realization

Article directory

  • foreword
    • 1. Create a prompt text component
    • 2. Implement the class MRzhGlobalListener for prompts
    • 3. The way to use MRzhGlobalListener

Foreword

The previous article introduced how to build a cesium + vue2.x project environment. This article mainly introduces how to generate mouse prompts on the Cesium map in the built project environment.

If you want to display drawing prompts in real time during the drawing process, the idea is as follows:

1. Create a prompt text component

Create a new .vue component with a random name. I call it cesiumTips.vue here. Its function is to display the prompt text when drawing. The code is as follows:

<template>
    <div id="cesiumTips" v-show="showTips">
        <div id="triangle-left" v-show="tipArray. length>0"></div>
        <p v-for="item in tipArray"><span>{<!-- -->{item}}</span></p>
    </div>
</template>

<script lang="ts">
    import {<!-- -->Component, Vue} from 'vue-property-decorator';
    import MRzhGlobalListener from "./MRzhGlobalListener";
    @Component({<!-- -->
        components: {<!-- -->

        },
    })
    export default class cesiumTips extends Vue {<!-- -->
        tipArray:any=[];
        showTips: boolean=false;
        mounted(): void {<!-- -->
            let tipsDom=document.getElementById('cesiumTips');
            MRzhGlobalListener.getInstance().setTipDom(tipsDom);
            MRzhGlobalListener.getInstance().setTipsCallback(this.tipsCallback)
        }
        tipsCallback(tipArray:any,showTips:boolean=true){<!-- -->
            this.showTips=showTips;
            this.tipArray=JSON.parse(JSON.stringify(tipArray));
        }
    }
</script>

<style lang="less">

    #cesiumTips{<!-- -->
        position: absolute;
        background: rgba(0,0,0,0.7);
        padding: 5px 10px;
        left: 20px;
        z-index: 100000;
        pointer-events: none;
        border-radius: 7px;
        p{<!-- -->
            text-align: center;
            color: white;
            line-height: 20px;
            font-size: 14px;
        }
        #triangle-left {<!-- -->
            width: 0;
            height: 0;
            position: absolute;
            top: 50%;
            left: -10px;
            margin-top: -5px;
            border-top: 5px solid transparent;
            border-right: 10px solid rgba(0,0,0,0.7);
            border-bottom: 5px solid transparent;
        }
    }
</style>

2. The class MRzhGlobalListener that implements the prompt

The idea is: monitor the movement of the mouse on the earth in real time, follow the position of the prompt component with the mouse, and design an interface that can modify the prompt text in real time. Here I define a class of MRzhGlobalListener to achieve it, and place this class at the same time as cesiumTips level directory, the code is as follows:

 import CesiumByZh from "../CesiumByZh"; //I will not write the CesiumByZh class here, please refer to https://blog.csdn.net/weixin_43812586/article/details/126172462

export default class MRzhGlobalListener{<!-- -->
public canvas = CesiumByZh.viewer.scene.canvas;
    public camera = CesiumByZh.viewer.scene.camera;
    public ellipsoid = CesiumByZh.viewer.scene.globe.ellipsoid;
    public viewer = CesiumByZh. viewer;
    public scene = CesiumByZh. viewer. scene;
    private handler: any = new CesiumByZh.Cesium.ScreenSpaceEventHandler(this.canvas);
    private static _instance: rtwsGlobalListener;
    private tipsCallback: any;//Callback function of tips
    private tipsDom: any;

    static getInstance() {<!-- -->
        if (MRzhGlobalListener._instance == null) {<!-- -->
            MRzhGlobalListener._instance = new MRzhGlobalListener();
        }
        return MRzhGlobalListener._instance;
    }

    setTipDom(tipsDom: any) {<!-- -->
        this.tipsDom = tipsDom;
    }

    setTipsCallback(callback: any) {<!-- -->
        this.tipsCallback = callback;
    }
    runTipsCallback(tipArray:any,showTips:boolean=true){<!-- -->
        this.tipsCallback(tipArray, showTips)
    }

    leftClickListener() {<!-- -->
        this.handler.setInputAction((event: any) => {<!-- -->
            let position = event. position;
            if (!CesiumByZh.Cesium.defined(position)) {<!-- -->
                return;
            }
            let ray = this. camera. getPickRay(position);
            if (!CesiumByZh.Cesium.defined(ray)) {<!-- -->
                return;
            }
            let cartesian = this.scene.globe.pick(ray, this.scene);
            if (!CesiumByZh.Cesium.defined(cartesian)) {<!-- -->
                return;
            }
            let pick = CesiumByZh.viewer.scene.pick(position);
        }, CesiumByZh.Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }

    rightClickListener() {<!-- -->
        this.handler.setInputAction((event: any) => {<!-- -->
            let position = event. position;
            if (!CesiumByZh.Cesium.defined(position)) {<!-- -->
                return;
            }
            let ray = this. camera. getPickRay(position);
            if (!CesiumByZh.Cesium.defined(ray)) {<!-- -->
                return;
            }
            let cartesian = this.scene.globe.pick(ray, this.scene);
            if (!CesiumByZh.Cesium.defined(cartesian)) {<!-- -->
                return;
            }
            let pick = CesiumByZh.viewer.scene.pick(position);
            
        }, CesiumByZh.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }

    mousemoveListener() {<!-- -->
        this.handler.setInputAction((event: any) => {<!-- -->
            let position = event. endPosition;
            if (!CesiumByZh.Cesium.defined(position)) {<!-- -->
                return;
            }
            let ray = this. camera. getPickRay(position);
            if (!CesiumByZh.Cesium.defined(ray)) {<!-- -->
                return;
            }
            let cartesian = this.scene.globe.pick(ray, this.scene);
            if (!CesiumByZh.Cesium.defined(cartesian)) {<!-- -->
                return;
            }
            if (this.tipsDom != null) {<!-- -->
                this.mouseMoveTipsFollow(cartesian);
            }
        }, CesiumByZh.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }

    //Mouse moves, prompt window follows
    mouseMoveTipsFollow(cartesian: any) {<!-- -->
        let divposition = CesiumByZh.Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.scene, cartesian);
        if (divposition) {<!-- -->
            this.tipsDom.style.left = divposition.x + 10 + 'px';
            this.tipsDom.style.top = divposition.y - this.tipsDom.offsetHeight / 2 + 'px';
        } else {<!-- -->
            this.tipsDom.style.left = -1000 + 'px';
            this.tipsDom.style.top = 0 + 'px';
        }
    }
}

3. Ways to use MRzhGlobalListener

First, import the cesiumTips.vue created in the first step into app.vue. I will not write any code in this step, and then add the following code to the CesiumByZh class.

/*CesiumByZh.viewer.scene.screenSpaceCameraController.tiltEventTypes = [CesiumByZh.Cesium.CameraEventType.MIDDLE_DRAG, CesiumByZh.Cesium.CameraEventType.PINCH];
if (funhander != null) {
     // @ts-ignore
     funhander();
 }*/
 //The previous ones are all the existing codes of CesiumByZh
MRzhGlobalListener.getInstance().mousemoveListener();//Here is the mobile monitor with prompts enabled

Then when you need prompts to appear on the map, call the runTipsCallback function under the MRzhGlobalListener class and pass in the corresponding prompt text. This function supports passing in an array, for example:

MRzhGlobalListener.getInstance().runTipsCallback(['Click to start drawing, right click to cancel']);

The effect is shown in the figure: