当前位置: 首页 > 文档资料 > Cesium 中文文档 >

Cesium 之自定义气泡窗口 infoWindow 篇

优质
小牛编辑
136浏览
2023-12-01

一、自定义气泡窗口与cesium默认窗口效果对比:

1.cesium点击弹出气泡窗口显示的位置固定在地图的右上角,默认效果:

2.对于习惯arcgis或者openlayer气泡窗口样式的giser来说,感觉不太适应,加上公司的领导也想要arcgis气泡窗口的那种样式效果,所以自定义了类似arcgis模板的气泡窗口模式,可以随着地图移动而移动,简单版本样式效果如下:

二、具体实现思路:

1.气泡窗css样式

   /*自定义气泡窗口样式模板*/
.closeButton{width:12px;height:12px;float:right;cursor:pointer;margin-top:4px;background:url(images/mainImage.png) no-repeat -31px -54px;}
.infowin3DContent{pointer-events:auto;}
.infowin3D{ width:300px; border:2px solid #CCC; position:absolute; background-color:#FFF;display:none;}
.arrow{ position:absolute; width:40px; height:40px; bottom:-40px;}
.arrow *{ display:block; border-width:20px; position:absolute; border-style:solid dashed dashed dashed; font-size:0; line-height:0; }
.arrow em{border-color:#CCC transparent transparent;}
.arrow span{border-color:#FFF transparent transparent; top:-3px;}

2.想要在地图显示气泡窗口样式的div挺容易的,但是想要实现气泡窗口随地图移动而移动,这点需要监听地图的范围变化事件以及移动监听事件才行。由于个人的研究cesium时间不久以及水平有限,尝试了这种思路,动手开发了一段时间,但是未能实现,还是比较遗憾的。可是这种效果又是领导想要的,逼急了,无意中发现了cesium的选中

是随着地图拖动而拖动的,F12扑捉看看,发现是SVG绘制出来的效果,放在cesium-selection-wrapperdiv里面。所以,个人决定从cesium源代码修改下手,新增气泡窗口div在里面,其实这种投机取巧的做法,不太推荐,破坏了源代码的原始性了。

修改源代码之处:SelectionIndicator构造函数里面,新增部分如下:

        //自定义部分
        var infowin = document.createElement('div');
        infowin.className= 'infowin3D';
        el.appendChild(infowin);
        //箭头
        var arrow = document.createElement('div');
        arrow.className= 'arrow';
        infowin.appendChild(arrow);
        var em = document.createElement("em");
        var span = document.createElement("span");
        arrow.appendChild(em);
        arrow.appendChild(span);
        //气泡窗口内容div
        var content = document.createElement('div');
        content.setAttribute('id', 'infowin3DContent');
        content.className= 'infowin3DContent';
        infowin.appendChild(content);
        //自定义部分结束

3.上面的步骤只是实现了一个空div气泡窗口,里面并没有内容信息的,内容是调用气泡窗口时候动态构造的,所以自己封装了一个调用气泡窗口的函数:

    /**
     * 弹出气泡窗口
     * @method infoWindow
     * @param  obj{position(必填):屏幕坐标,destination(必填):跳转目的点,content(必填):气泡窗口内容,css(可填):设置css的width,height}
     * @return 返回选中的模型Entity
     */    
    infoWindow: function (obj) {
        var picked = this.cesiumViewer.scene.pick(obj.position);
        if (Cesium.defined(picked)) {
            var id = Cesium.defaultValue(picked.id, picked.primitive.id);
            if (id instanceof Cesium.Entity) {
                if(obj.destination){
                    this.cesiumViewer.camera.flyTo({//初始化跳转某个地方
                        destination : obj.destination
                    });    
                }
                //填充内容
                $(".cesium-selection-wrapper").show();
                $("#infowin3DContent").empty();
                $("#infowin3DContent").append(obj.content);
                //css存在情况下,设置css
                if(obj.css && obj.css.width)
                   $(".infowin3D").css("width",obj.css.width);
                if(obj.css && obj.css.height)
                    $(".infowin3D").css("height",obj.css.height);
                  $(".infowin3D").css("margin-top",-($(".infowin3D").height()-30));
                  $(".arrow").css("left",($(".infowin3D").width()/2-20));
                  $(".infowin3D").css("margin-left",-($(".infowin3D").width()/2-76));
                $(".infowin3D").show();
                $("#infoClose3D").click(function () {
                    $(".cesium-selection-wrapper").hide();
                    $(".infowin3D").hide();
                });                
                return id;
            }
        }    
    }

4.调用:

 //调用接口-气泡窗口
    var handler3D = new Cesium.ScreenSpaceEventHandler(cesium.cesiumViewer.scene.canvas);
    handler3D.setInputAction(function(movement) {
        //点击弹出气泡窗口
        var pick = cesium.cesiumViewer.scene.pick(movement.position);
        if(pick && pick.id){//选中某模型
            var cartographic = Cesium.Cartographic.fromCartesian(pick.id._position._value);//世界坐标转地理坐标(弧度)
            var point=[ cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180];//地理坐标(弧度)转经纬度坐标
            var destination=Cesium.Cartesian3.fromDegrees(point[0], point[1], 3000.0);
            var content ="<div  style='border-bottom: 1px solid #C6CBCE;'>"+
                "<span style='margin-left: 5px;'>测试测试1</span>"+
                "<div id='infoClose3D' class='closeButton' style='margin-right: 4px;'></div>"+
                "</div>"+                                    
                "<div>"+
                "<label>测试1:</label><label>测试1</label></br>"+
                "<label>测试2:</label><label>测试2</label></br>"+
                "<label>测试3:</label><label>测试3</label></br>"+
                "</div>";
            var obj = {position:movement.position,destination:destination,content:content};
            cesium.infoWindow(obj);            
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);