Cesium 之实现鹰眼功能(可拖拽矩形框定位范围)

本文实现的一种思路如下:

1、通过Cesium.Viewer创建鹰眼地图,获取主地图的当前范围和中心点位置,在鹰眼地图中创建矩形用于定位参考。

2、主地图联动鹰眼图 

注册主地图相机的移动前(moveStart)和移动后(moveEnd)事件,来联动鹰眼地图的范围。

3、鹰眼地图联动主地图

通过拖拽矩形框,改变鹰眼地图范围后联动改变主地图范围。

使用鼠标的LEFT_DOWN、LEFT_UP和MOUSE_MOVE事件来实现矩形框实体位置的变化。

直接上代码,有需要的小伙伴可以参考。

JS代码

///
// 模块描述:鹰眼地图,和主地图进行联动
///
define([
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/array',
    'dojo/_base/html',
    'dojo/topic',
    'jimu/BaseWidget'
],
function (declare,
          lang,
          array,
          html,
          topic,
          BaseWidget
) {

    var CesiumViewTool = (function () {//http://blog.sina.com.cn/s/blog_15e866bbe0102y5no.html
        function _() {
        }

        _.GetViewExtent = function (viewer) {
            var extent = {};
            var scene = viewer.scene;
            var ellipsoid = scene.globe.ellipsoid;
            var canvas = scene.canvas;

            var car3_lt = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), ellipsoid);// canvas左上角
            var car3_rb = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width, canvas.height), ellipsoid); // canvas右下角

            // 当canvas左上角和右下角全部在椭球体上
            if (car3_lt && car3_rb) {
                var carto_lt = ellipsoid.cartesianToCartographic(car3_lt);
                var carto_rb = ellipsoid.cartesianToCartographic(car3_rb);
                extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude);
                extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude);
                extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude);
                extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude);
            } else if (!car3_lt && car3_rb) { // 当canvas左上角不在但右下角在椭球体上
                return null;
            }
            else if (car3_lt && !car3_rb) { // 当canvas左上角在但右下角不在椭球体上
                return null;
                
            } else if (!car3_lt && !car3_rb) {
                return null;
            }

            // 获取高度
            extent.height = Math.ceil(viewer.camera.positionCartographic.height);
            return extent;
        }

        _.GetViewCenter = function (viewer) {
            var result = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2));
            if (result) {
            } else {
                return null;
            }
            var curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
            var lon = curPosition.longitude * 180 / Math.PI;
            var lat = curPosition.latitude * 180 / Math.PI;
            var height = viewer.camera.positionCartographic.height;
            return {
                lgtd: lon,
                lttd: lat,
                height: height
            };
        }
        return _;
    })();
    var MoveEntity = (function () {
        var leftDownFlag = false;
        var pointDraged = null;
        var viewer;
        var handler,cartesian;
        var startPoint;
        var polylinePreviousCoordinates;
        var polygonPreviousCoordinates;
        var rectanglePreviousCoordinates={};
        var moveEndCallBack,moveStartCallBack;
        function ConstructMoveEntity(options,_moveStartCallBack,_moveEndCallBack) {
            viewer = options.viewer;
            moveEndCallBack=_moveEndCallBack;
            moveStartCallBack=_moveStartCallBack;
            handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
            Init();
        }

        function Init() {
            // Select plane when mouse down
            handler.setInputAction(function (movement) {
                pointDraged = viewer.scene.pick(movement.position);//选取当前的entity
                leftDownFlag = true;
                if (pointDraged) {
                    if(moveStartCallBack){
                        moveStartCallBack();
                    }
                    //记录按下去的坐标
                    startPoint = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid)
                    viewer.scene.screenSpaceCameraController.enableRotate = false;//锁定相机
                    viewer.scene.screenSpaceCameraController.enableTranslate = false;
                    if(pointDraged.id.polygon){
                        // 1.54版本
                        // polygonPreviousCoordinates = pointDraged.id.polygon.hierarchy.getValue();
                        // 1.67版本
                        polygonPreviousCoordinates = pointDraged.id.polygon.hierarchy.getValue().positions;
                    }
                }
            }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

            // Release plane on mouse up
            handler.setInputAction(function () {
                if(pointDraged&&moveEndCallBack){
                    moveEndCallBack(cartesian)
                }
                leftDownFlag = false;
                pointDraged = null;
                viewer.scene.screenSpaceCameraController.enableInputs = true;
                viewer.scene.screenSpaceCameraController.enableRotate = true;//锁定相机
                viewer.scene.screenSpaceCameraController.enableTranslate = true;
                
                // handler.destroy();
            }, Cesium.ScreenSpaceEventType.LEFT_UP);
            // Update plane on mouse move
            handler.setInputAction(function (movement) {
                if (leftDownFlag === true && pointDraged != null) {
                    //记录尾随的坐标
                    //pickposition改为pickEllipsoid,鹰眼不加入地形
                    let startPosition = viewer.scene.camera.pickEllipsoid(movement.startPosition, viewer.scene.globe.ellipsoid)
                    let endPosition = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid)
                    pointDraged.id.position = new Cesium.CallbackProperty(function () {
                        return endPosition;
                    }, false);//防止闪烁,在移动的过程console.log(pointDraged.id);
                    //计算每次的偏差
                    let changed_x = endPosition.x-startPosition.x;
                    let changed_y = endPosition.y-startPosition.y;
                    let changed_z = endPosition.z-startPosition.z;

                   

                    if(pointDraged.id.polygon){
                        let currentsPoint=[];
                        for(let i=0;i<polygonPreviousCoordinates.length;i++){
                            polygonPreviousCoordinates[i].x=polygonPreviousCoordinates[i].x+changed_x;
                            polygonPreviousCoordinates[i].y=polygonPreviousCoordinates[i].y+changed_y;
                            polygonPreviousCoordinates[i].z=polygonPreviousCoordinates[i].z+changed_z;
                            currentsPoint.push(polygonPreviousCoordinates[i])
                        }
                        var holes=pointDraged.id.polygon.hierarchy.getValue().holes;
                        var hierarchy=new Cesium.PolygonHierarchy(currentsPoint, holes)
                        // supermap cesium1.67不可用
                        //     pointDraged.id.polygon.hierarchy=new Cesium.CallbackProperty (() => {
                        //         return pointDraged.id.polygon.hierarchy;
                        //   }, false);
                        pointDraged.id.polygon.hierarchy=hierarchy
                        // // 1.54版本
                        //     pointDraged.id.polygon.hierarchy=new Cesium.CallbackProperty (() => {
                        //         return currentsPoint;
                        //  }, false);
                       
                    }

                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        }
        return ConstructMoveEntity;
    })();

    return declare([BaseWidget], {
        baseClass: 'jimu-widget-EagleEye',

        layers:{},
        startup: function () {
            this.inherited(arguments);
            
            this.initEagleEye();
            var self = this;
            var updateTimer,updateTimer2;
            if (true) {
                var camera = window.viewer.camera;
                camera.moveStart.addEventListener(function() {
                    if (!Cesium.defined(updateTimer)) {
                        updateTimer = window.setInterval(self.extentChange, 1000);
                    }
                });
                camera.moveEnd.addEventListener(function() {
                    if (Cesium.defined(updateTimer)) {
                        window.clearInterval(updateTimer);
                        updateTimer = undefined;
                    }
                    self.extentChange();
                       
                });
            }
            MoveEntity({ 'viewer': this.eagleEyemap},
            function(){
                console.log(`开始移动`)
            },
            function(c){
                console.log(`移动完成`)
                self.extentChangeEyeMap(self.bound);
                
            });
        },
        extentChangeEyeMap:function(entity){
            if(this.eagleEyemap){
                // 获取多边形的positions列表 并计算它的中心点
                // 1.54版本
                // var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now());
                // 1.67版本
                var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;

                var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
                var ellipsoid=this.eagleEyemap.scene.globe.ellipsoid;
                var cartesian3=new Cesium.Cartesian3(polyCenter.x,polyCenter.y,polyCenter.z);
                var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
                var lat=Cesium.Math.toDegrees(cartographic.latitude);
                var lng=Cesium.Math.toDegrees(cartographic.longitude);
                // 保留主地图原有相机高度
                var height=window.viewer.camera.positionCartographic.height;

                window.viewer.camera.setView({
                        destination : Cesium.Cartesian3.fromDegrees(lng,lat,height)
                });
            } 
        },
        extentChange:function(){//改变之后
            var extent = CesiumViewTool.GetViewExtent(window.viewer);
            var center = CesiumViewTool.GetViewCenter(window.viewer);
            if(extent&&this.createExtentPolygon){
                this.createExtentPolygon([extent.xmin,extent.ymin],[extent.xmax,extent.ymax],center);
            }else{
                if(!center)return;
                if(this.eagleEyemap){
                    this.eagleEyemap.camera.setView({
                        destination : Cesium.Cartesian3.fromDegrees(center.lgtd, center.lttd, center.height*4)
                    });
                }
            }
            
        },

        createExtentPolygon: function (pt1,pt2,center) {

            if(!center)return;
            var ringsArray = [];
            ringsArray.push(pt1[0], pt1[1]);
            ringsArray.push(pt2[0], pt1[1]);
            ringsArray.push(pt2[0], pt2[1]);
            ringsArray.push(pt1[0], pt2[1]);
            ringsArray.push(pt1[0], pt1[1]);
            if(this.bound){
                this.bound.polygon.hierarchy = Cesium.Cartesian3.fromDegreesArray(ringsArray);
                this.eagleEyemap.camera.setView({
                    destination : Cesium.Cartesian3.fromDegrees(center.lgtd, center.lttd, center.height*4)
                });
                return;
            }
            this.bound = this.eagleEyemap.entities.add({
                name : 'polygon',
                position:Cesium.Cartesian3.fromDegrees(center.lgtd, center.lttd),
                polygon : {
                    hierarchy : Cesium.Cartesian3.fromDegreesArray(ringsArray),
                    material : Cesium.Color.RED.withAlpha(0.5),
                    outline : true,
                    outlineColor : Cesium.Color.RED,
                    outlineWidth:2.0
                }
            });
            this.eagleEyemap.camera.setView({
                destination : Cesium.Cartesian3.fromDegrees(center.lgtd, center.lttd, center.height*4)
            });

        },
        initEagleEye:function(){
            //添加鹰眼
            this.eagleEyemap = new Cesium.Viewer(this.eagleEye,{

                "animation":false,
                "baseLayerPicker":false,
                "fullscreenButton":false,
                "geocoder":false,
                "homeButton":false,
                "infoBox" : false,
                "sceneModePicker":false,
                "selectionIndicator" : false ,
                "timeline":false,
                "navigationHelpButton":false,
                "scene3DOnly" : false,
                "navigationInstructionsInitiallyVisible":false,
                "terrainExaggeration":1,
                "showRenderLoopErrors":false,
                "sceneMode":Cesium.SceneMode.SCENE2D,
                "imageryProvider":null
            });
            //去掉版权
            this.eagleEyemap._cesiumWidget._creditContainer.style.display = "none";
            this.eagleEyemap.scene.globe.depthTestAgainstTerrain = true;
            var layers=this.appConfig.map.overViewLayers;
            if(layers&&layers.length>0){
                layers.forEach(x=>{
                    let layer=null;
                    //公开底图自定义封装库
                   //天地图
                   let type=x.type.toLowerCase();
                   if(type=="tdt"){
                       layer=new Cesium.TdtImageryProvider(x)
                   }
                   // 高德
                   else if (type=="gd"){
                       layer=new Cesium.AmapImageryProvider(x)
                   }
                   // 腾讯
                   else if (type=="tx"){
                       layer=new Cesium.TencentImageryProvider(x)
                   }
                   // 百度
                   else if (type=="bd"){
                       layer=new Cesium.BaiduImageryProvider(x)
                   }
                   // 谷歌
                   else if (type=="google"){
                       layer=new Cesium.GoogleImageryProvider(x)
                   }
                   // 其他cesium支持的类型
                   else if (type == "url") {
                       layer = new Cesium.UrlTemplateImageryProvider(x);
                   } else if (type == "wmts") {
                       layer = new Cesium.WebMapTileServiceImageryProvider(x);
                   } else if (type == "supermap") {
                       layer = new Cesium.SuperMapImageryProvider(x);
                   } else if (type == "arcgis") {
                       layer = new Cesium.ArcGisMapServerImageryProvider(x);
                   }
                   if(layer){
                    this.eagleEyemap.imageryLayers.addImageryProvider(layer)
                   }
                })
            }
            var extent = {
                "xmin": 86.06689524994869,
                "ymin": 22.108857182532834,
                "xmax": 124.9584857499487,
                "ymax": 48.08052948253283};

            var west = extent.xmin;
            var south = extent.ymin;
            var east =extent.xmax;
            var north =extent.ymax;

            this.eagleEyemap.camera.setView({
                destination : Cesium.Rectangle.fromDegrees(west, south, east, north)
            });
            // this.vis()
        },
        onOpen: function () {
            //面板打开的时候触发 (when open this panel trigger)
        },

        onClose: function () {
            //面板关闭的时候触发 (when this panel is closed trigger)
        },

        onMinimize: function () {
            this.resize();
        },

        onMaximize: function () {
            this.resize();
        },

        resize: function () {

        },

        destroy: function () {
            //销毁的时候触发
            //todo
            //do something before this func
            this.inherited(arguments);
        },
        flag:true,
        vis:function(){
           if(this.flag){
               $(this.eagleEye).hide();
               this.visNode.innerHTML = "显示鹰眼";

               $(this.domNode).height(30);
               $(this.domNode).width(74);
           }else{
               $(this.eagleEye).show();
               $(this.domNode).height(this.position.height);
               $(this.domNode).width(this.position.width);
               this.visNode.innerHTML = "隐藏鹰眼";
           }

            this.flag = !this.flag;
        }

    });
});

里面中底图的判断使用了前一篇所讲的在线底图封装

html代码

<div>
    <div style="width:100%;height:100%;    border: 3px solid #b8b5b5;
    border-radius: 5px;" data-dojo-attach-point="eagleEye"></div>

    <div style="    position: absolute;cursor: pointer;
    bottom: 2px;
    left: 2px;
    height: 29px;
    width: 74px;
    padding: 3px;
    background-color: #0a001f;"><a  style="    color: white;
    font-size: 14px;
    padding: 5px;" data-dojo-attach-point="visNode"  data-dojo-attach-event="click:vis">隐藏鹰眼</a></div>
</div>

结果截图:

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xizhjxust_GIS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值