Mapbox | setStyle切换源保留添加图层

发布时间 2023-09-18 11:19:30作者: 槑孒

问题描述

在使用 Mapbox-GL 构建地图 Web 应用程序。它有很多很酷的功能。根据需求在地图上设置了切换基本地图(即卫星、地形等)的按钮。

遇到的问题是,当使用setStyle()更改样式时,它会删除作为图层加载的多边形并重新加载地图,而且会把我后续单独添加的图层给删除,我希望能够更改基本地图并保留这些图层。

有没有办法在不重新加载地图或至少不删除图层的情况下更改样式?

解决方法

与 Leaftlet 等地图库不同,Mapbox GL JS 没有底图其他图层的概念。

所有图层都是同一个实体的一部分:样式。

因此,您需要保留数据层的一些状态,并在每次更改时调用它的 addLayer。

说白了,就是定义一个全局变量,专门把后面单独添加的图层存进去并做顺序处理,在每次切换style源的时候,监视styledata事件从而把这些图层再添加到地图。

点击查看示例代码
<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8' />
  <title></title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <link href="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css" rel="stylesheet">
  <script src="https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"></script>
</head>

<body>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    .map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }

    .menu {
      position: absolute;
      z-index: 1;
      top: 10px;
      right: 10px;
      border-radius: 3px;
      width: 120px;
    }

    .menu button {
      font: 13px/20px 'Helvetica Neue', sans-serif;
      background: #3887be;
      color: #fff;
      display: block;
      width: 100%;
      margin: 0;
      padding: 0;
      padding: 10px;
      border: none;
      border-bottom: 1px solid rgba(0, 0, 0, 0.25);
      cursor: pointer;
    }

    .menu button:first-child {
      border-radius: 3px 3px 0 0;
    }

    .menu button:last-child {
      border-radius: 0 0 3px 3px;
      border: none;
    }

    .menu button.active,
    .menu button:hover {
      background-color: #52a1d8;
    }
  </style>
  <nav id='menu' class='menu'></nav>
  <div id='map' class='map'></div>

  <script>
    mapboxgl.accessToken = 'pk.eyJ1IjoiZWNob2h5ZSIsImEiOiJjbGNuM3hmeXo2a2FjM3Fsa2JpM2praGp4In0.olt3jKXnWYuYiDmiNvvndg';
    var map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v11',
      center: [113, 32],
      zoom: 4
    });

    var baseLayers = [{
      label: 'Streets',
      id: 'streets-v11'
    }, {
      label: 'Light',
      id: 'light-v10'
    }, {
      label: 'Dark',
      id: 'dark-v10'
    }];

    var menu = document.getElementById('menu');
    var geojson;

    function addDataLayer() {
      map.addSource('urban-areas', {
        'type': 'geojson',
        'data': geojson
      });

      map.addLayer({
        'id': 'urban-areas-fill',
        'type': 'fill',
        'source': 'urban-areas',
        'paint': {
          'fill-color': 'red',
          'fill-opacity': 0.4
        }
      });
    }
    map.on('styledata', function () {
      if (geojson) addDataLayer();
    });

    map.on('load', function () {
      fetch('https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_urban_areas.geojson').then(e => e.json()).then(e => {
        geojson = e;
        addDataLayer();
      })
      baseLayers.forEach(function (l) {
        var button = document.createElement('button');
        button.textContent = l.label;
        button.addEventListener('click', function () {
          map.setStyle('mapbox://styles/mapbox/' + l.id);
        });
        menu.appendChild(button);
      });
    });
  </script>

</body>

</html>

Mapbox-GL setStyle 移除图层
Mapbox-GL setStyle 删除图层 - stack overflow