Cesium | Ceisum双球体鹰眼图实现(Property与Camera实现)

2,481 阅读3分钟

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

前言

Cesium 并没有像二维的地图 api 系统一样向我们提供鹰眼图这样一个 gis 相关的功能,但在业务场景中却经常被要求添加鹰眼图,因为 Cesium 是一个三维球体,所以它的鹰眼图主要有两个方向:主视图三维球体鹰眼图二维平面和主视图鹰眼图均为球体。第一个方向在网上已有大神通过leaflet实现(指路:OverviewMapForCesium),这篇文章主要来实现一下第二个方向,双球体的鹰眼实现。

二维鹰眼.gif

实现效果

鹰眼.gif

思路

首先,既然是两个球体,那么主视图和鹰眼图要分别定义两个Viewer生成两个球体,并将鹰眼图中的Viewer所有额外功能组件全部配置为false,只保留最干净的球体即可。

接着我们需要将球体的相机控制全部关闭,只通过主视图球体的操作来同步到鹰眼图的球体。

最后将这个球体放到 dom 中,展示在主视图下方即可。

实现

我们直接将鹰眼这个功能封装成一个类,即插即用,首先我们定义暴露出来的方法AddEyeMap,接受两个参数,第一个是要插入鹰眼图的 DOM 的 id,第二个是主视图的Viewer,方便我们进行同步。

// 调用
Cesium.AddEyeMap("eyeContainer", Viewer)
// 暴露方法export default function AddEyeMap(domId, viewer) {
  if (!domId) return
  const dom = document.getElementById(domId)
  dom.classList.add('eye-map-style')
  if (!dom) {
    throw new Error(`${domId}不存在!`)
  }
  // ……
}
​
.eye-map-style {
  width: 200px;
  height: 200px;
  position: absolute;
  bottom: 0;
  right: 0;
  border: 1px solid blue;
  z-index: 99999;
}

AddEyeMap方法中,我们需要生成我们的鹰眼图球体,并进行相关配置:

class EyeMap {
  constructor(id) {
    this.viewer = new Cesium.Viewer(id, {
      animation: false,
      baseLayerPicker: false,
      fullscreenButton: false,
      geocoder: false,
      homeButton: false,
      sceneModePicker: false,
      selectionIndicator: false,
      timeline: false,
      navigationHelpButton: false,
      infoBox: false,
      navigationInstructionsInitiallyVisible: false,
    })
    this.viewer._cesiumWidget._creditContainer.style.display = 'none'
​
    const control = this.viewer.scene.screenSpaceCameraController
    control.enableRotate = false
    control.enableTranslate = false
    control.enableZoom = false
    control.enableTilt = false
    control.enableLook = false
  }
}

EyeMap类实现了我们思路中的第二步,接着还需要给类一个同步视角的方法,利用主视图传递过来的Viewer设置鹰眼图中的球体相机角度:

EyeMap.prototype._sync = function(viewer){
    this.viewer.camera.flyTo({
      destination: viewer.camera.position,
      orientation: {
        heading: viewer.camera.heading,
        pitch: viewer.camera.pitch,
        roll: viewer.camera.roll,
      },
      duration: 0.0,
    })
  }

接下来我们在AddEyeMap中 new 一个鹰眼球实例,并通过CallbackProperty实现每时每刻与主视图同步:

export default function AddEyeMap(id, viewer) {
  // ……
  const eyeMap = new EyeMap(id)
  // 同步
  viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(0, 0),
    label: {
      text: new Cesium.CallbackProperty(() => {
        eyeMap._sync(viewer)
        return ''
      }, true),
    },
  })
}

上述代码中我们通过添加了一个空字符串的label,利用它的CallbackProperty实现了每时每刻调用syncViewer方法来同步两个球的相机视角。

最后

本文实现了基本的双球鹰眼图,只提供一个实现思路,后续可以在此基础上对功能进行扩展。也欢迎研究Cesium和GIS相关小伙伴提出相关建议,共同学习~

相关文章

\