Cesium(九)鹰眼功能【转】

Cesium鹰眼实现的功能,有两种方式:一种声明两个viewer,另一种就是通过Leaflet。这里我们采用第二种方式,用到一位道友自定义鹰眼插件,这里我们稍微改进一下(ES6方式),下面我们来介绍一下如何实现

一、效果图
二、实现过程
1、插件下载网址https://github.com/leation/OverviewMapForCesium
2、使用环境

Cesium
Leaflet
Vue
webpack
3、安装Leaflet
npm install leaflet --save
3、html声明

<div id="overview" class="leaflet-control-minimap"></div>
4、leaflet引入

import * as L from 'leaflet'
5、css引入

<style>
@import '../css/Control.MiniMap.css';
#overview {
z-index: 99998;
width: 150px;
height: 150px;
position: absolute;
right: 10px;
bottom: 50px;
}
</style>

6、vue中使用

methods:{
initOverview: function (viewer) {
var url = "http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}";
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
}
}; 
var overviewCtr =new CesiumOverviewMapControl(viewer, layer, options);
} 
}

mounted() {
.........
this.initOverview(viewer);
},

7、CesiumOverviewMapControl改写

 

import Cesium from 'cesium/Cesium'
var CesiumOverviewMapControl = function () {
  this.init.apply(this, arguments)
}
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)
          _this._miniMap.fitBounds(zrect)
          _this._setDisplay(_this._decideMinimized())
        } else {
          _this._miniMapMoving = false
        }
        _this._aimingRect.setBounds(rect)
      })
      camera.moveStart.addEventListener(function (e) {
        var rect = _this._getViewRange()
        _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
  },
  _addToggleButton: function () {
    this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
      '', this._toggleButtonInitialTitleText(), ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' +
                this.options.position), this._container, this._toggleDisplayButtonClicked, this) : undefined
    // this._toggleDisplayButton.style.zIndex = 99999;
    this._toggleDisplayButton.style.width = this.options.collapsedWidth + 'px'
    this._toggleDisplayButton.style.height = this.options.collapsedHeight + 'px'
  },

  _toggleButtonInitialTitleText: function () {
    if (this.options.minimized) {
      return this.options.strings.showText
    } else {
      return this.options.strings.hideText
    }
  },

  _createButton: function (html, title, className, container, fn, context) {
    var link = L.DomUtil.create('a', className, container)
    link.innerHTML = html
    link.href = '#'
    link.title = title

    var stop = L.DomEvent.stopPropagation

    L.DomEvent
      .on(link, 'click', stop)
      .on(link, 'mousedown', stop)
      .on(link, 'dblclick', stop)
      .on(link, 'click', L.DomEvent.preventDefault)
      .on(link, 'click', fn, context)

    return link
  },

  _toggleDisplayButtonClicked: function () {
    this._userToggledDisplay = true
    if (!this._minimized) {
      this._minimize()
    } else {
      this._restore()
    }
  },
  _showInitView: function () {
    var rect = this._getViewRange()
    var zrect = this._getZoomOutRange(rect)
    this._miniMap.fitBounds(zrect)
  },
  _setDisplay: function (minimize) {
    if (minimize !== this._minimized) {
      if (!this._minimized) {
        this._minimize()
      } else {
        this._restore()
      }
    }
  },
  _minimize: function () {
    // hide the minimap
    if (this.options.toggleDisplay) {
      this._container.style.width = this.options.collapsedWidth + 'px'
      this._container.style.height = this.options.collapsedHeight + 'px'
      this._toggleDisplayButton.className += (' minimized-' + this.options.position)
      this._toggleDisplayButton.title = this.options.strings.showText
    } else {
      this._container.style.display = 'none'
    }
    this._minimized = true
    this._onToggle()
  },
  _restore: function () {
    if (this.options.toggleDisplay) {
      this._container.style.width = this.options.width + 'px'
      this._container.style.height = this.options.height + 'px'
      this._toggleDisplayButton.className = this._toggleDisplayButton.className
        .replace('minimized-' + this.options.position, '')
      this._toggleDisplayButton.title = this.options.strings.hideText
    } else {
      this._container.style.display = 'block'
    }
    this._minimized = false
    this._onToggle()
  },
  _onMiniMapMoveStarted: function (e) {
    if (!this.options.centerFixed) {
      var lastAimingRect = this._aimingRect.getBounds()
      var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest())
      var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast())
      this._lastAimingRectPosition = { sw: sw, ne: ne }
    }
  },
  _onMiniMapMoving: function (e) {
    if (!this.options.centerFixed) {
      if (!this._viewerMoving && this._lastAimingRectPosition) {
        this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw), this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne)))
        this._shadowRect.setStyle({ opacity: 1, fillOpacity: 0.3 })
      }
    }
  },
  _onMiniMapMoved: function (e) {
    if (!this._viewerMoving) {
      this._miniMapMoving = true

      var rect = this._shadowRect.getBounds()
      var west = rect.getWest()
      var east = rect.getEast()
      var north = rect.getNorth()
      var south = rect.getSouth()
      var destination = Cesium.Rectangle.fromDegrees(west, south, east, north)
      var orientation = {
        heading: Cesium.Math.toRadians(0),
        pitch: Cesium.Math.toRadians(-90),
        roll: 0.0
      }
      this.viewer.scene.camera.setView({
        destination: destination,
        orientation: orientation
      })
      this._shadowRect.setStyle({ opacity: 0, fillOpacity: 0 })
    } else {
      this._viewerMoving = false
    }
  },
  _isZoomLevelFixed: function () {
    var zoomLevelFixed = this.options.zoomLevelFixed
    return this._isDefined(zoomLevelFixed) && this._isInteger(zoomLevelFixed)
  },
  _decideMinimized: function () {
    if (this._userToggledDisplay) {
      return this._minimized
    }

    if (this.options.autoToggleDisplay) {
      var bounds = this._getViewRange()
      if (bounds.contains(this._miniMap.getBounds())) {
        return true
      }
      return false
    }

    return this._minimized
  },
  _isInteger: function (value) {
    return typeof value === 'number'
  },
  _isDefined: function (value) {
    return typeof value !== 'undefined'
  },
  _onToggle: function () {
    L.Util.requestAnimFrame(function () {
      L.DomEvent.on(this._container, 'transitionend', this._fireToggleEvents, this)
      if (!L.Browser.any3d) {
        L.Util.requestAnimFrame(this._fireToggleEvents, this)
      }
    }, this)
  },
  _fireToggleEvents: function () {
    L.DomEvent.off(this._container, 'transitionend', this._fireToggleEvents, this)
  },
  _getViewRange: function () {
    var viewer = this.viewer
    var camera = viewer.scene.camera
    var range = camera.computeViewRectangle()
    var west = range.west / Math.PI * 180
    var east = range.east / Math.PI * 180
    var north = range.north / Math.PI * 180
    var south = range.south / Math.PI * 180
    var bounds = new L.LatLngBounds(
      new L.LatLng(north, west),
      new L.LatLng(south, east)
    )
    return bounds
  },
  _getZoomOutRange: function (rect) {
    var west = rect.getWest()
    var east = rect.getEast()
    var north = rect.getNorth()
    var south = rect.getSouth()
    var factor = 3.0
    var xdis = Math.abs(east - west)
    var ydis = Math.abs(north - south)
    var xoff = xdis * (factor - 1) / 2.0
    var yoff = ydis * (factor - 1) / 2.0
    west -= xoff
    east += xoff
    north += yoff
    south -= yoff
    if (west < -180) {
      west = -180
    }
    if (east > 180) {
      east = 180
    }
    if (north > 90) {
      north = 90
    }
    if (south < -90) {
      south = -90
    }
    var bounds = new L.LatLngBounds(
      new L.LatLng(north, west),
      new L.LatLng(south, east)
    )
    return bounds
  }
}
export default CesiumOverviewMapControl

 


原文链接:https://blog.csdn.net/weixin_40184249/article/details/95507300

posted on 2022-03-11 09:49  3D入魔  阅读(713)  评论(0编辑  收藏  举报