以下提供的这段代码片段,作用是在 Cesium 里,根据相机高度自动切换底图:

  • 低空:用 OSM(看细节)
  • 高空:用 Google 影像(看大范围)

实现 近看细节,远看整体 的效果。

完整代码片段如下:

const camera = viewer.camera;
const scratchCartesian = new Cesium.Cartesian3();

// 移除原有图层
function _removeBaseLayer() {
  var layers = viewer.imageryLayers;
  var baseLayer = layers.get(0);
  layers.remove(baseLayer);
  return layers;
}

// OSM 图层
const osm_tile = new Cesium.UrlTemplateImageryProvider({
  url: 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
  credit: 'Open street map',
  maximumLevel: 18
});

// Google 图层
const google_tile =  new Cesium.UrlTemplateImageryProvider({
  url: 'https://mt0.google.com/vt/lyrs=s@0&hl=en&x={x}&y={y}&z={z}',
  credit: 'google imagery',
  maximumLevel: 18
});

// 监听镜头高度,超过某一阈值时切换图层。
let imagery = 'google';
camera.moveEnd.addEventListener(function () {
  const endPos = camera.positionWC.clone(scratchCartesian);
  const endHeight = Cesium.Cartographic.fromCartesian(endPos).height;

  console.log(`end height: ${endHeight}, tile: ${imagery}`);

  if (endHeight < 100000) {
    if (imagery === 'google') {
      console.log("change imagery to osm");

      const layers = _removeBaseLayer();
      layers.addImageryProvider(osm_tile);
      imagery = 'osm';
    }
  } else {
    if (imagery === 'osm') {
      console.log("change imagery to google map");

      const layers = _removeBaseLayer();
      layers.addImageryProvider(google_tile);
      imagery = 'google';
    }
  }
});

关键思路

  1. 准备相机与临时变量

    const camera = viewer.camera;
    const scratchCartesian = new Cesium.Cartesian3();
    
  2. 封装一个“移除当前底图”的小工具函数

    默认第 0 个图层是底图,把它删掉:

    function _removeBaseLayer() {
      var layers = viewer.imageryLayers;
      var baseLayer = layers.get(0);
      layers.remove(baseLayer);
      return layers;
    }
    
  3. 预先定义两套底图 Provider

    • OSM:

      const osm_tile = new Cesium.UrlTemplateImageryProvider({
        url: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
        credit: "Open street map",
        maximumLevel: 18,
      });
      
    • Google 影像:

      const google_tile = new Cesium.UrlTemplateImageryProvider({
        url: "https://mt0.google.com/vt/lyrs=s@0&hl=en&x={x}&y={y}&z={z}",
        credit: "google imagery",
        maximumLevel: 18,
      });
      
  4. 用一个变量记录当前底图类型

    let imagery = "google"; // 初始假设是 google
    
  5. 监听 camera.moveEnd,在相机停止移动时判断高度

    camera.moveEnd.addEventListener(function () {
      const endPos = camera.positionWC.clone(scratchCartesian);
      const endHeight = Cesium.Cartographic.fromCartesian(endPos).height;
    
      console.log(`end height: ${endHeight}, tile: ${imagery}`);
    });
    
  6. 根据高度阈值切换底图

    这里用 100000 米作为阈值:

    if (endHeight < 100000) {
      // 低空:切到 OSM
      if (imagery === "google") {
        console.log("change imagery to osm");
        const layers = _removeBaseLayer();
        layers.addImageryProvider(osm_tile);
        imagery = "osm";
      }
    } else {
      // 高空:切回 Google
      if (imagery === "osm") {
        console.log("change imagery to google map");
        const layers = _removeBaseLayer();
        layers.addImageryProvider(google_tile);
        imagery = "google";
      }
    }