cesium 入门开发系列地图鹰眼功能

459 阅读2分钟

内容概览

  1. cesium 结合 leaflet 实现鹰眼图
  2. cesium 自身 api 实现鹰眼图
  3. 源代码 demo 下载
  • cesium 结合 leaflet 实现鹰眼图方式
    效果图如下

初始化 cesium

    function initialGlobeView() {
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjRjNGFjNy1jNDM3LTQzMTktODVlYS05YmFmOTAxYjk5MWUiLCJpZCI6Mzk5MSwic2NvcGVzIjpbImFzbCIsImFzciIsImFzdyIsImdjIl0sImlhdCI6MTUzOTU3OTE2NX0.-25udUzENRJ66mnICMK8Hfc6xgF_VP7P4sWkSHaUjOQ';
        var image_Source = new Cesium.UrlTemplateImageryProvider({
            // url: 'http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}',
            url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
            credit: ''
        });
        viewer = new Cesium.Viewer('cesiumContainer', {
            geocoder: false,
            homeButton: false,
            sceneModePicker: false,
            fullscreenButton: false,
            vrButton: false,
            baseLayerPicker: false,
            infoBox: false,
            selectionIndicator: true,
            animation: false,
            timeline: false,
            shouldAnimate: true,
            navigationHelpButton: false,
            navigationInstructionsInitiallyVisible: false,
            imageryProvider: image_Source
        });
        viewer.scene.globe.enableLighting = false;
        viewer.scene.globe.depthTestAgainstTerrain = true;
        viewer.scene.globe.showGroundAtmosphere = false;
    }

初始化鹰眼

    function initOverview() {
        var url =
            "http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}";
            // 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}';
        var layer = new L.TileLayer(url, {
            minZoom: 0,
            maxZoom: 20
        });
        var container = document.getElementById("overview");
        var options = {
            container: container,
            toggleDisplay: true,
            width: 150,
            height: 150,
            position: "topright",
            aimingRectOptions: {
                color: "#ff1100",
                weight: 3
            },
            shadowRectOptions: {
                color: "#0000AA",
                weight: 1,
                opacity: 0,
                fillOpacity: 0
            }
        };
        overviewCtr = new CesiumOverviewMapControl(viewer, layer, options);
    }

核心鹰眼代码,通过监听 cesium 视图变化事件联动 leaflet 视图同步,同时也监听 leaflet 视图变化事件联动 cesium 视图同步

CesiumOverviewMapControl.prototype = {
    _container: null,
    _miniMap: null,
    _viewerMoving: false,
    _miniMapMoving: false,
    _userToggledDisplay: false,
    _minimized: false,
    viewer: null,
    tileLayer: null,
    options: {
        position: 'bottomleft',
        toggleDisplay: true,
        zoomLevelOffset: -5,
        zoomLevelFixed: false,
        centerFixed: false,
        zoomControl: false,
        zoomAnimation: false,
        autoToggleDisplay: false,
        minimized: false,
        width: 150,
        height: 150,
        collapsedWidth: 19,
        collapsedHeight: 19,
        aimingRectOptions: { color: '#ff7800', weight: 1, interactive: false },
        shadowRectOptions: { color: '#000000', weight: 1, interactive: false, opacity: 0, fillOpacity: 0 },
        strings: { hideText: '隐藏鹰眼', showText: '显示鹰眼' },
        mapOptions: {
            toggleDisplay: true,
            aimingRectOptions: {
                color: "#ff1100",
                weight: 3
            },
            shadowRectOptions: {
                color: "#0000AA",
                weight: 1,
                opacity: 0,
                fillOpacity: 0
            }
        }
    },
    init: function (viewer, layer, options) {
        this.viewer = viewer;
        this.tileLayer = layer;
        this._container = options.container;
        L.Util.setOptions(this, options);

        this.options.aimingRectOptions.interactive = false;
        this.options.shadowRectOptions.interactive = false;

        this._initMap();
        this._showInitView();
    },
    updateAimingRect: function () {
        var _this = this;
        var rect = _this._getViewRange();
        _this._aimingRect.setBounds(rect);
    },
    _initMap: function () {
        var _this = this;

        this._container.style.width = this.options.width + 'px';
        this._container.style.height = this.options.height + 'px';

        L.DomEvent.disableClickPropagation(_this._container);
        L.DomEvent.on(_this._container, 'mousewheel', L.DomEvent.stopPropagation);

        var mapOptions = {
            attributionControl: false,
            dragging: !_this.options.centerFixed,
            zoomControl: _this.options.zoomControl,
            zoomAnimation: _this.options.zoomAnimation,
            autoToggleDisplay: _this.options.autoToggleDisplay,
            touchZoom: _this.options.centerFixed ? 'center' : !_this._isZoomLevelFixed(),
            scrollWheelZoom: _this.options.centerFixed ? 'center' : !_this._isZoomLevelFixed(),
            doubleClickZoom: _this.options.centerFixed ? 'center' : !_this._isZoomLevelFixed(),
            boxZoom: !_this._isZoomLevelFixed(),
            crs: L.CRS.EPSG3857,
            center: [30, 120],
            zoom: 1
        };
        mapOptions = L.Util.extend(_this.options.mapOptions, mapOptions);  // merge
        // with
        // priority
        // of
        // the
        // local
        // mapOptions
        // object.

        _this._miniMap = new L.Map(_this._container, mapOptions);

        var layer = this.tileLayer;
        _this._miniMap.addLayer(layer);

        // These bools are used to prevent infinite loops of the two maps
        // notifying each other that they've moved.
        _this._viewerMoving = true;
        _this._miniMapMoving = false;

        // Keep a record of _this to prevent auto toggling when the user
        // explicitly doesn't want it.
        _this._userToggledDisplay = false;
        _this._minimized = false;

        if (this.options.toggleDisplay) {
            this._addToggleButton();
        }

        _this._miniMap.whenReady(L.Util.bind(function () {
            var bounds = _this._getViewRange();
            _this._aimingRect = L.rectangle(bounds, _this.options.aimingRectOptions).addTo(_this._miniMap);
            _this._shadowRect = L.rectangle(bounds, _this.options.shadowRectOptions).addTo(_this._miniMap);

            var camera = _this.viewer.scene.camera;
            camera.moveEnd.addEventListener(function (e) {
                var rect = _this._getViewRange();
                if (!_this._miniMapMoving) {
                    _this._viewerMoving = true;
                    var zrect = _this._getZoomOutRange(rect);
                    if(zrect){
                        _this._miniMap.fitBounds(zrect);
                        _this._setDisplay(_this._decideMinimized());
                    }
                } else {
                    _this._miniMapMoving = false;
                }
                if(rect)
                   _this._aimingRect.setBounds(rect);
            });
            camera.moveStart.addEventListener(function (e) {
                var rect = _this._getViewRange();
                if(rect)
                   _this._aimingRect.setBounds(rect);
            });

            _this._miniMap.on('movestart', _this._onMiniMapMoveStarted, _this);
            _this._miniMap.on('move', _this._onMiniMapMoving, _this);
            _this._miniMap.on('moveend', _this._onMiniMapMoved, _this);
        }, _this));

        return _this._container;
    },
……
  • cesium 自身 api 实现鹰眼图方式
    效果图:

实现思路,创建两个视图,主视图 viewer 以及右下角鹰眼视图 viewer1,通过监听 viewer 变化来同步 viewer1

        var viewer = new Cesium.Viewer('cesiumContainer', {
            imageryProvider: new Cesium.UrlTemplateImageryProvider({
              url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
              credit: ''
            }),
            geocoder: false,
            homeButton: false,
            sceneModePicker: false,
            baseLayerPicker: false,
            navigationHelpButton: false,
            animation: false,
            timeline: false,
            fullscreenButton: false,
            vrButton: false
        });
        viewer._cesiumWidget._creditContainer.style.display = "none";
        var viewer1 = new Cesium.Viewer('eye', {
            imageryProvider: new Cesium.UrlTemplateImageryProvider({
              url: 'https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
              credit: ''
            }),
            geocoder: false,
            homeButton: false,
            sceneModePicker: false,
            baseLayerPicker: false,
            navigationHelpButton: false,
            animation: false,
            timeline: false,
            fullscreenButton: false,
            vrButton: false
        });
        viewer1._cesiumWidget._creditContainer.style.display = "none";
        let control = viewer1.scene.screenSpaceCameraController;
        control.enableRotate = false;
        control.enableTranslate = false;
        control.enableZoom = false;
        control.enableTilt = false;
        control.enableLook = false;
        let syncViewer = function() {
            viewer1.camera.flyTo({
                destination: viewer.camera.position,
                orientation: {
                    heading: viewer.camera.heading,
                    pitch: viewer.camera.pitch,
                    roll: viewer.camera.roll
                },
                duration: 0.0
            });
        };
        viewer.scene.preRender.addEventListener(syncViewer);

参考资料:
1.github.com/leation/Ove…
2.gitee.com/HQCode/Cesi…

link==>