基于超图(Cesium)的webgl demo开发

加载场景/图层

要求:

  • 进入页面默认展示完整地球,2.5s后打开默认场景与图层(以飞行方式进入);
  • 自动生成左侧图层树,可对各图层进行显示隐藏控制;(可自己写树或者调用插件)
    实现方法
  1. 设置延时打开三维场景(setTimeout),由于scene.open(url)会直接将镜头切至指定场景,我使用了两个('cesiumContainer'),在第二个div中设置打开场景,第一个div中设置相机视角展示完整地球,随后使用flyto命令飞入场景并删除第二个div
    html部分代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="shortcut icon" href="star.png" type="image/x-icon">
    <link href="assets/Cesium/Widgets/widgets.css" rel="stylesheet">
    <link href="assets/layui/css/layui.css" rel="stylesheet">
    <link href="src/css/common.css" rel="stylesheet">
    <link href="assets/css/main.css" rel="stylesheet">
    <link rel="stylesheet" href="boot-strap/bootstrap.css">
    <link href="boot-strap/pretty.css" rel="stylesheet">

    <style>
        #toolbar {
            position: absolute;
            width: 350px;
            height: 50px;
            top: 0px;
            left: 100px;
            margin: 0;
        }

        #tool-menu {
            position: absolute;
            width: 150px;
            height: 350px;
            top: 50px;
            left: 10px;
            margin: 0;
        }

        #start {
            position: absolute;
            width: 50px;
            height: 50px;
            top: 0px;
            left: 0px;
            margin: 0px;
        }

        #layerTree {
            position: absolute;
            left: 10px;
            top: 20px;
            width: 360px;
            max-height: 800px;
            overflow: auto;
            z-index: 999;
        }
    </style>
    <title>永和九年岁在癸丑暮春之初会于会稽山阴之兰亭修禊事也</title>
</head>

<body>
    <div id='cesiumContainer'></div>
    <div id='v2'></div>

    <div id='tool-menu' class='tool-menu'>
        <div id='layerTree'></div>
    </div>

    <div id="toolbar" class="layui-btn-group">
        <button type="button" id="distance" class="layui-btn layui-btn-radius layui-btn-normal">测距</button>
        <button type="button" id="area" class="layui-btn layui-btn-radius layui-btn-normal">测面</button>
        <button type="button" id="height" class="layui-btn layui-btn-radius layui-btn-normal">测高</button>
        <button type="button" id="clear" class="layui-btn layui-btn-radius layui-btn-danger">清除</button>
    </div>
    <button id="start" class="layui-btn layui-btn-radius layui-btn-fluid">标</button>

    <div id="bubble" class="bubble" style="bottom:0;left:82%;display:none;">
        <div id="tools" style="text-align : right">
            <span style="color: rgb(95, 74, 121);padding: 5px;position: absolute;left: 10px;top: 4px;">对象属性</span>
            <span class="fui-export" id="bubblePosition" style="color: darkgrey; padding:5px" title="停靠"></span>
            <span class="fui-cross" title="关闭" id="close" style="color: darkgrey;padding:5px"></span>
        </div>
        <div style="overflow-y:scroll;height:150px" id="tableContainer">
            <table id="tab"></table>
        </div>
    </div>
    <div id="bubble1" class="bubble" style="top:0;left:82%;display:block;width: 400px;visibility: hidden;"><!--class="bubble"-->
        <div id="tools1" style="text-align : right">
            <span style="color: rgb(95, 74, 121);padding: 5px;position: absolute;left: 10px;top: 4px;">该点经纬度为</span>
            <span class="fui-export" id="bubblePosition1" style="color: darkgrey; padding:5px" title="停靠"></span>
            <span class="fui-cross" title="关闭" id="close1" style="color: darkgrey;padding:5px"></span>
        </div>
        <div style="overflow-y:scroll;height:190px" id="tableContainer1"><table id="tab1"></table></div>
    </div>  
    <script src="assets/Cesium/config.js"></script>
    <script src="boot-strap/jquery.min.3.2.1.js"></script>
    <script src="assets/js/SuperMap.Include.js"></script>
    <script src="assets/js/SuperMap-7.1-11828.js"></script>
    <script src="assets/js/Convert.js"></script>
    <script src="boot-strap/bootstrap.min.js"></script>
    <script src="boot-strap/bootstrap-select.min.js"></script>
    <script src="boot-strap/bootstrap-treeview.js"></script>
    <script src="assets/layui/layui.all.js"></script>
    <script src="assets/layer/layer.js"></script>
    <script src="index.js"></script>
    <script src="assets/Cesium/require.min.js" data-main="assets/Cesium/main"></script>
</body>
</html>

js代码

    setTimeout(function () {
        Cesium.when.all(mo, function (layers) {
            //获取第一个图层的矩形范围
            var bounds = layers[0].layerBounds;
            if (bounds) {
                viewer.scene.camera.flyTo({
                    destination: bounds,
                    duration: 5
                });
            }
        })
        console.log('2.5秒经过!');
        scene.open(url).then((layers)=>{
  ...........................................................
      $('#v2').remove()
    }, 2500);
  1. 图层树实现
    使用bootstrap-treeview实现。参考[https://blog.csdn.net/hailangtuteng/article/details/80842730]了解格式。遍历layers(批量模型),取图层名与layer项加入新的列表。在遍历过程中对每个layer项建立query参数,绑定模型信息。(setQueryParameter语法糖,本质为发送query返回信息)。通过控制树中每个节点的visible属性完成图层的显隐控制。
    代码如下
     var treeData = [];
            for (var layer of layers) {
                treeData.push({
                    text: layer.name,
                    selectable: true,
                    layer: layer,
                    showDel: true,
                    state: {
                        checked: true
                    }
                })
                if (data3dMap[layer.name]) {
                    layer.setQueryParameter({
                        url: "超图iserver数据服务",
                        dataSourceName: data3dMap[layer.name].dataSourceName,
                        dataSetName: data3dMap[layer.name].dataSetName,
                    });
                }
            }
           $('#layerTree').treeview({
                data: [{ text: "图层列表", selectable: true, nodes: treeData, showDel: true, fontSize: '1pt', state: { checked: true } }],
                showIcon: true,
                showCheckbox: true,
                backColor: 'transparent',
                color: 'gery',
                //通过NodeChecked状态设置子图层的显示与隐藏的切换
                onNodeChecked: function (evt, node) {
                    console.log('NodeChecked', node)
                    node.layer.visible = true;
                },
                onNodeUnchecked: function (evt, node) {
                    console.log('NodeUnChecked', node)
                    node.layer.visible = false;
                },
            });
图层树

点击展示建筑信息

要求:

  • 编写通用显示展示气泡;
  • 点击某图元查询并展示相应的信息(以气泡方式展示);
  • 属性信息以layui数据表格展示;(数据表格,非静态表格)
    实现方法
    与图层控制在一起。已经绑定模型信息,需要pickEvent添加监听事件。监听到模型pick后将模型信息写入气泡中弹窗显示。
//pickEvent
            var table = document.getElementById("tab");
            viewer.pickEvent.addEventListener(function (feature) {
                $("#bubble").show();
                console.log('listener', feature)
                for (i = table.rows.length - 1; i > -1; i--) {
                    table.deleteRow(i);
                }
                for (var key in feature) {
                    var newRow = table.insertRow();
                    var cell1 = newRow.insertCell();
                    var cell2 = newRow.insertCell();
                    cell1.innerHTML = key;
                    cell2.innerHTML = feature[key];
                }
            });
            $("#bubblePosition").click(function () {
                console.log('clicked')
                if ($("#bubblePosition").hasClass("fui-export")) {
                    viewer.customInfobox = undefined;
                    $("#bubble").removeClass("bubble").addClass("float");
                    $("#bubblePosition").removeClass("fui-export").addClass("fui-bubble");
                    $("#bubblePosition")[0].title = "悬浮";
                    $("#bubble").css({ 'left': '82%', 'bottom': '45%' });
                    $("#tableContainer").css({ 'height': '350px' });
                }
                else if ($("#bubblePosition").hasClass("fui-bubble")) {
                    $("#bubble").removeClass("float").addClass("bubble");
                    $("#bubblePosition").removeClass("fui-bubble").addClass("fui-export");
                    $("#bubblePosition")[0].title = "停靠";
                    $("#tableContainer").css({ 'height': '150px' });
                    viewer.customInfobox = infoboxContainer;
                }
            });
            $("#close").click(function () {
                $("#bubble").hide();
            });
        })

在这段代码中

     var treeData = [];
            for (var layer of layers) {
                treeData.push({
                    text: layer.name,
                    selectable: true,
                    layer: layer,
                    showDel: true,
                    state: {
                        checked: true
                    }
                })
                if (data3dMap[layer.name]) {
                    layer.setQueryParameter({
                        url: "超图iserver数据服务",
                        dataSourceName: data3dMap[layer.name].dataSourceName,
                        dataSetName: data3dMap[layer.name].dataSetName,
                    });
                }
            }

data3dMap为

    var data3dMap = {
        "图层名": {
            dataSourceName: "数据源名称",
            dataSetName: "数据集名称"
        },
      ..................................................
    }

这是为了使layer项中的图层名能对应到服务器对应数据服务中。使用if语句判断映射是否存在。


属性查询

实现基础测量工具功能

要求:

   function Mymeasure() {

        //测量
        var handlerDis, handlerArea, handlerHeight;
        var clampMode = 0; // 空间模式
        //初始化测量距离
        handlerDis = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.Distance, clampMode);
        //注册测距功能事件
        handlerDis.measureEvt.addEventListener(function (result) {
            var dis = Number(result.distance);
            var distance = dis > 1000 ? (dis / 1000).toFixed(2) + 'km' : dis.toFixed(2) + 'm';
            handlerDis.disLabel.text = '距离:' + distance;

        });
        handlerDis.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });

        //初始化测量面积
        handlerArea = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.Area, clampMode);
        handlerArea.measureEvt.addEventListener(function (result) {
            var mj = Number(result.area);
            var area = mj > 1000000 ? (mj / 1000000).toFixed(2) + 'km²' : mj.toFixed(2) + '㎡'
            handlerArea.areaLabel.text = '面积:' + area;
        });
        handlerArea.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });


        //初始化测量高度
        handlerHeight = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.DVH);
        handlerHeight.measureEvt.addEventListener(function (result) {
            var distance = result.distance > 1000 ? (result.distance / 1000).toFixed(2) + 'km' : result.distance + 'm';
            var vHeight = result.verticalHeight > 1000 ? (result.verticalHeight / 1000).toFixed(2) + 'km' : result.verticalHeight + 'm';
            var hDistance = result.horizontalDistance > 1000 ? (result.horizontalDistance / 1000).toFixed(2) + 'km' : result.horizontalDistance + 'm';
            handlerHeight.disLabel.text = '空间距离:' + distance;
            handlerHeight.vLabel.text = '垂直高度:' + vHeight;
            handlerHeight.hLabel.text = '水平距离:' + hDistance;
        });
        handlerHeight.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });

        $('#distance').click(function () {
            deactiveAll();
            handlerDis && handlerDis.activate();
        });

        $('#area').click(function () {
            deactiveAll();
            handlerArea && handlerArea.activate();
        });
        $('#height').click(function () {
            deactiveAll();
            handlerHeight && handlerHeight.activate();
        });
        $('#clear').click(function () {
            clearAll();
        });
        function clearAll() {
            handlerDis && handlerDis.clear();
            handlerArea && handlerArea.clear();
            handlerHeight && handlerHeight.clear();
        }

        function deactiveAll() {
            handlerDis && handlerDis.deactivate();
            handlerArea && handlerArea.deactivate();
            handlerHeight && handlerHeight.deactivate();
        }
    }
    Mymeasure();
测面积

标记功能

要求:

  • 功能按钮左上角展示;
  • 鼠标左键在场景中点击选取位置,可在所在位置添加一个图标(大小:32*32),并在图标下方显示经纬度
    实现方法
    按钮左上角用css完成,鼠标左键点击开启,右键移除所有实体并取消左键绑定事件。超图demo方法开始时可用,最后调试时在左键点击事件后进入vm出错,实在水平有限调不好,也找不到原因。
    超图demo实现方法:
jwdcx: function () {
            $('#start').click(function () {
                var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                handler.setInputAction(function (e) {
                    viewer.entities.removeAll();
                    var position = scene.pickPosition(e.position);

                    //将笛卡尔坐标转化为经纬度坐标
                    var cartographic = Cesium.Cartographic.fromCartesian(position);
                    var longitude = Cesium.Math.toDegrees(cartographic.longitude);
                    var latitude = Cesium.Math.toDegrees(cartographic.latitude);

                    //创建弹出框信息
                    var entity = new Cesium.Entity({
                        name: "位置信息",
                        description: createDescription(Cesium, [longitude, latitude])
                    });
                    viewer.selectedEntity = entity;

                    //在点击位置添加对应点
                    viewer.entities.add(new Cesium.Entity({
                        position: Cesium.Cartesian3.fromDegrees(longitude, latitude),
                        billboard: { image: logo }
                    }));
                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                //创建描述位置的对话框
                function createDescription(Cesium, properties) {
                    var simpleStyleIdentifiers = ['经度', '纬度'];
                    var html = '';
                    for (var key in properties) {
                        if (properties.hasOwnProperty(key)) {
                            if (simpleStyleIdentifiers.indexOf(key) !== -1) {
                                continue;
                            }
                            var value = properties[key];
                            if (Cesium.defined(value) && value !== '') {
                                html += '<tr><td>' + simpleStyleIdentifiers[key] + '</td><td>' + value + '</td></tr>';
                            }
                        }
                    }
                    if (html.length > 0) {
                        html = '<table class="zebra"><tbody>' + html + '</tbody></table>';
                    }
                    return html;
                }
            });
        },

调试时可进入createDescription函数且无报错,在左键点击事件后内部函数出错。

我参考https://blog.csdn.net/wc063013/article/details/86491479完成了该功能

$('#start').click(function () {
        var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        var table1 = document.getElementById("tableContainer1");
        var globe = viewer.scene.globe;
        var _position, _pm_position, _cartesian;
        var camera = viewer.scene.camera;

        //设置鼠标左键单击回调事件
        handler.setInputAction(function (e) {
            $('#bubble1').show();
            viewer.entities.removeAll();
            var position = scene.pickPosition(e.position);
            var positionObj = scene.pick(e.position);
            var cartographic = Cesium.Cartographic.fromCartesian(position);
            var longitude = Cesium.Math.toDegrees(cartographic.longitude);
            var latitude = Cesium.Math.toDegrees(cartographic.latitude);
            var height = cartographic.height;
            // var altitude = Math.ceil(viewer.camera.positionCartographic.height)
            var cartesian = scene.globe.pick(camera.getPickRay(e.position), scene);
            var cartographic = scene.globe.ellipsoid.cartesianToCartographic(cartesian);
            var picks = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, cartesian);
            var bubble = document.getElementById("bubble1");
            // 设置弹出框信息
            bubble.style.left = e.position.x - 70 + "px";
            var divheight = bubble.offsetHeight;
            var divy = e.position.y - divheight - 50;//50px为.bubble:after--20x50
            bubble.style.top = divy + "px";
            bubble.style.visibility = "visible"; //visibility: "hidden" 

            _position = e.position;
            _cartesian = cartesian;
            _pm_position = { x: picks.x, y: picks.y }

            //在点击位置添加对应框
            viewer.entities.add(new Cesium.Entity({
                name : '位置信息',
                position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height + 10),
                billboard: { image: logo, width: 32, height: 32 },
                description : createDescription(Cesium,table1,[longitude,latitude,height])                
            }));
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

         $("#close1").click(function () {
            $("#bubble1").hide();
        });

//右键功能
        handler.setInputAction(function (e) {
            viewer.entities.removeAll();
            handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

        //创建描述位置的对话框
        function createDescription(Cesium, table1, properties) {
            var simpleStyleIdentifiers = ['经度', '纬度', '高度'];
            var html = '';
            for (var key in properties) {
                if (properties.hasOwnProperty(key)) {
                    if (simpleStyleIdentifiers.indexOf(key) !== -1) {
                        continue;
                    }
                    var value = properties[key];
                    if (Cesium.defined(value) && value !== '') {
                        html += '<tr><td>' + simpleStyleIdentifiers[key] + '</td><td>' + value + '</td></tr>';
                    }
                }
            }
            if (html.length > 0) {
                html = '<table class="zebra"><tbody>' + html + '</tbody></table>';
            }
            table1.innerHTML = html;
        }
        var _pm_position_2;
        //每帧渲染结束监听
        viewer.scene.postRender.addEventListener(function (e) {

            if (_pm_position != _pm_position_2) {
                _pm_position_2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, _cartesian);
                var popw = document.getElementById("bubble1").offsetWidth;
                var poph = document.getElementById("bubble1").offsetHeight;

                var trackPopUpContent_ = window.document.getElementById("bubble1");
                //trackPopUpContent_.style.visibility = "visible";
                trackPopUpContent_.style.left = _pm_position_2.x - 70 + "px";
                trackPopUpContent_.style.top = _pm_position_2.y - (poph + 50) + "px";
            }
        });
    });
标记点

结语

通过开发这个demo我大概摸清了超图数据服务和超图的二次开发流程,或者说是基于cesium的三次开发流程^^
作为新手,有待学习的地方还很多。贴上完整js代码。

function onload(Cesium) {
    console.log('The world!')
    var viewer = new Cesium.Viewer('cesiumContainer');
    var logo = 'star.png';
    var widget = viewer.cesiumWidget;
    var scene = viewer.scene;
    var url = '三维服务地址';
    var canvas = scene.canvas;
    var imageryLayers = viewer.imageryLayers;
    var baseLayer = imageryLayers.get(0);
    scene.camera.frustum.near = 0.01;
    viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({
        credit: new Cesium.Credit('天地图全球影像服务     数据来源:国家地理信息公共服务平台 & 四川省测绘地理信息局'),
        token: URL_CONFIG.TOKEN_TIANDITU
    }));
    viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(0, 0, 19009000)
    });
    var v2 = new Cesium.Viewer('v2')
    var mo = v2.scene.open(url)
    v2.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({
        credit: new Cesium.Credit('天地图全球影像服务     数据来源:国家地理信息公共服务平台 & 四川省测绘地理信息局'),
        token: URL_CONFIG.TOKEN_TIANDITU
    }));
    var globe = viewer.scene.globe;
    viewer.scene.undergroundMode = true; //设置开启地下场景
    viewer.scene.screenSpaceCameraController.minimumZoomDistance = -1000;//设置相机最小缩放距离,距离地表-1000米
    viewer.scene.terrainProvider.isCreateSkirt = false; // 关闭裙边
    viewer._cesiumWidget._creditContainer.style.display = "none";//隐藏logo


    var infoboxContainer = document.getElementById("bubble")
    viewer.customInfobox = infoboxContainer
    var data3dMap = {
        "13单元": {
            dataSourceName: "13单元-8",
            dataSetName: "十三单元"
        },
        "一单元": {
            dataSourceName: "01单元-8",
            dataSetName: "一单元"
        },
        "二单元": {
            dataSourceName: "02单元-8",
            dataSetName: "二单元"
        },
        "Dataset_四单元": {
            dataSourceName: "04单元-01-8",
            dataSetName: "Dataset_四单元"
        },
        "十二单元": {
            dataSourceName: "12单元-8",
            dataSetName: "十二单元"
        },
    }

    setTimeout(function () {
        Cesium.when.all(mo, function (layers) {
            var bounds = layers[0].layerBounds;
            if (bounds) {
                viewer.scene.camera.flyTo({
                    destination: bounds,
                    duration: 5
                });
            }
        })
        console.log('2.5秒经过!');
        scene.open(url).then((layers) => {
            // console.log(layers)
            var treeData = [];
            for (var layer of layers) {
                treeData.push({
                    text: layer.name,
                    selectable: true,
                    layer: layer,
                    showDel: true,
                    state: {
                        checked: true
                    }
                })
                if (data3dMap[layer.name]) {
                    layer.setQueryParameter({
                        url: "数据服务地址",
                        dataSourceName: data3dMap[layer.name].dataSourceName,
                        dataSetName: data3dMap[layer.name].dataSetName,
                    });
                }
            }
            console.log('treeData', treeData)
            $('#layerTree').treeview({
                data: [{ text: "图层列表", selectable: true, nodes: treeData, showDel: true, fontSize: '1pt', state: { checked: true } }],
                showIcon: true,
                showCheckbox: true,
                backColor: 'transparent',
                color: 'gery',
                onNodeChecked: function (evt, node) {
                    console.log('NodeChecked', node)
                    node.layer.visible = true;
                },
                onNodeUnchecked: function (evt, node) {
                    console.log('NodeUnChecked', node)
                    node.layer.visible = false;
                },
            });
            //PICKEVENT
            var table = document.getElementById("tab");
            viewer.pickEvent.addEventListener(function (feature) {
                $("#bubble").show();
                console.log('listener', feature)
                for (i = table.rows.length - 1; i > -1; i--) {
                    table.deleteRow(i);
                }
                for (var key in feature) {
                    var newRow = table.insertRow();
                    var cell1 = newRow.insertCell();
                    var cell2 = newRow.insertCell();
                    cell1.innerHTML = key;
                    cell2.innerHTML = feature[key];
                }
            });
            $("#bubblePosition").click(function () {
                console.log('clicked')
                if ($("#bubblePosition").hasClass("fui-export")) {
                    viewer.customInfobox = undefined;
                    $("#bubble").removeClass("bubble").addClass("float");
                    $("#bubblePosition").removeClass("fui-export").addClass("fui-bubble");
                    $("#bubblePosition")[0].title = "悬浮";
                    $("#bubble").css({ 'left': '82%', 'bottom': '45%' });
                    $("#tableContainer").css({ 'height': '350px' });
                }
                else if ($("#bubblePosition").hasClass("fui-bubble")) {
                    $("#bubble").removeClass("float").addClass("bubble");
                    $("#bubblePosition").removeClass("fui-bubble").addClass("fui-export");
                    $("#bubblePosition")[0].title = "停靠";
                    $("#tableContainer").css({ 'height': '150px' });
                    viewer.customInfobox = infoboxContainer;
                }
            });
            $("#close").click(function () {
                $("#bubble").hide();
            });
        })    
        $('#v2').remove()
    }, 2500);



    $('#start').click(function () {
        var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        var table1 = document.getElementById("tableContainer1");
        var globe = viewer.scene.globe;
        var _position, _pm_position, _cartesian;
        var camera = viewer.scene.camera;
        handler.setInputAction(function (e) {
            $('#bubble1').show();
            viewer.entities.removeAll();
            var position = scene.pickPosition(e.position);
            var positionObj = scene.pick(e.position);
            var cartographic = Cesium.Cartographic.fromCartesian(position);
            var longitude = Cesium.Math.toDegrees(cartographic.longitude);
            var latitude = Cesium.Math.toDegrees(cartographic.latitude);
            var height = cartographic.height;
            var cartesian = scene.globe.pick(camera.getPickRay(e.position), scene);
            var cartographic = scene.globe.ellipsoid.cartesianToCartographic(cartesian);
            var picks = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, cartesian);
            var bubble = document.getElementById("bubble1");
            bubble.style.left = e.position.x - 70 + "px";
            var divheight = bubble.offsetHeight;
            var divy = e.position.y - divheight - 50;//50px为.bubble:after--20x50
            bubble.style.top = divy + "px";
            bubble.style.visibility = "visible"; //visibility: "hidden" 
            _position = e.position;
            _cartesian = cartesian;
            _pm_position = { x: picks.x, y: picks.y }
            viewer.entities.add(new Cesium.Entity({
                name : '位置信息',
                position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height + 10),
                billboard: { image: logo, width: 32, height: 32 },
                description : createDescription(Cesium,table1,[longitude,latitude,height])                
            }));  
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

         $("#close1").click(function () {
            $("#bubble1").hide();
        });

        handler.setInputAction(function (e) {
            viewer.entities.removeAll();
            handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);


        function createDescription(Cesium, table1, properties) {
            var simpleStyleIdentifiers = ['经度', '纬度', '高度'];
            var html = '';
            for (var key in properties) {
                if (properties.hasOwnProperty(key)) {
                    if (simpleStyleIdentifiers.indexOf(key) !== -1) {
                        continue;
                    }
                    var value = properties[key];
                    if (Cesium.defined(value) && value !== '') {
                        html += '<tr><td>' + simpleStyleIdentifiers[key] + '</td><td>' + value + '</td></tr>';
                    }
                }
            }
            if (html.length > 0) {
                html = '<table class="zebra"><tbody>' + html + '</tbody></table>';
            }
            table1.innerHTML = html;
        }
        var _pm_position_2;
        viewer.scene.postRender.addEventListener(function (e) {
            if (_pm_position != _pm_position_2) {
                _pm_position_2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, _cartesian);
                var popw = document.getElementById("bubble1").offsetWidth;
                var poph = document.getElementById("bubble1").offsetHeight;

                var trackPopUpContent_ = window.document.getElementById("bubble1");
                //trackPopUpContent_.style.visibility = "visible";
                trackPopUpContent_.style.left = _pm_position_2.x - 70 + "px";
                trackPopUpContent_.style.top = _pm_position_2.y - (poph + 50) + "px";
            }
        });
    });
    function Mymeasure() {

        //测量
        var handlerDis, handlerArea, handlerHeight;
        var clampMode = 0; // 空间模式
        //初始化测量距离
        handlerDis = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.Distance, clampMode);
        //注册测距功能事件
        handlerDis.measureEvt.addEventListener(function (result) {
            var dis = Number(result.distance);
            var distance = dis > 1000 ? (dis / 1000).toFixed(2) + 'km' : dis.toFixed(2) + 'm';
            handlerDis.disLabel.text = '距离:' + distance;

        });
        handlerDis.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });

        //初始化测量面积
        handlerArea = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.Area, clampMode);
        handlerArea.measureEvt.addEventListener(function (result) {
            var mj = Number(result.area);
            var area = mj > 1000000 ? (mj / 1000000).toFixed(2) + 'km²' : mj.toFixed(2) + '㎡'
            handlerArea.areaLabel.text = '面积:' + area;
        });
        handlerArea.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });


        //初始化测量高度
        handlerHeight = new Cesium.MeasureHandler(viewer, Cesium.MeasureMode.DVH);
        handlerHeight.measureEvt.addEventListener(function (result) {
            var distance = result.distance > 1000 ? (result.distance / 1000).toFixed(2) + 'km' : result.distance + 'm';
            var vHeight = result.verticalHeight > 1000 ? (result.verticalHeight / 1000).toFixed(2) + 'km' : result.verticalHeight + 'm';
            var hDistance = result.horizontalDistance > 1000 ? (result.horizontalDistance / 1000).toFixed(2) + 'km' : result.horizontalDistance + 'm';
            handlerHeight.disLabel.text = '空间距离:' + distance;
            handlerHeight.vLabel.text = '垂直高度:' + vHeight;
            handlerHeight.hLabel.text = '水平距离:' + hDistance;
        });
        handlerHeight.activeEvt.addEventListener(function (isActive) {
            if (isActive == true) {
                viewer.enableCursorStyle = false;
                viewer._element.style.cursor = '';
                $('body').removeClass('measureCur').addClass('measureCur');
            }
            else {
                viewer.enableCursorStyle = true;
                $('body').removeClass('measureCur');
            }
        });

        $('#distance').click(function () {
            deactiveAll();
            handlerDis && handlerDis.activate();
        });

        $('#area').click(function () {
            deactiveAll();
            handlerArea && handlerArea.activate();
        });
        $('#height').click(function () {
            deactiveAll();
            handlerHeight && handlerHeight.activate();
        });
        $('#clear').click(function () {
            clearAll();
        });
        function clearAll() {
            handlerDis && handlerDis.clear();
            handlerArea && handlerArea.clear();
            handlerHeight && handlerHeight.clear();
        }

        function deactiveAll() {
            handlerDis && handlerDis.deactivate();
            handlerArea && handlerArea.deactivate();
            handlerHeight && handlerHeight.deactivate();
        }
    }
    Mymeasure();
    layer.msg('Test version,Marry Christmax!')

};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351