Mapbox GL JS:样式未完成加载

fra*_*lbo 5 mapbox mapbox-gl mapbox-gl-js

我有一张地图,我们可以经典地从一种样式切换到另一种样式,例如从街道到卫星。

我想知道样式已加载,然后添加一个图层。

根据文档,我试图等待样式加载以基于GEOJson数据集添加图层。

当页面加载并触发时,该方法效果很好,map.on('load')但是当我更改样式时出现错误,因此从添加图层时map.on('styledataloading'),甚至在Firefox中出现内存问题。

我的代码是:

mapboxgl.accessToken = 'pk.token';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v10',
    center: [5,45.5],
    zoom: 7
});

map.on('load', function () {

    loadRegionMask();
});

map.on('styledataloading', function (styledata) {

    if (map.isStyleLoaded()) {
        loadRegionMask();
    }
});

$('#typeMap').on('click', function switchLayer(layer) {
    var layerId = layer.target.control.id;

    switch (layerId) {
        case 'streets':
            map.setStyle('mapbox://styles/mapbox/' + layerId + '-v10');
        break;

        case 'satellite':
            map.setStyle('mapbox://styles/mapbox/satellite-streets-v9');
        break;
    }
});

function loadJSON(callback) {   

  var xobj = new XMLHttpRequest();
      xobj.overrideMimeType("application/json");

  xobj.open('GET', 'regions.json', true);

  xobj.onreadystatechange = function () {
        if (xobj.readyState == 4 && xobj.status == "200") {
          callback(xobj.responseText);
        }
  };
  xobj.send(null);  
}

function loadRegionMask() {

  loadJSON(function(response) {

    var geoPoints_JSON = JSON.parse(response);

    map.addSource("region-boundaries", {
      'type': 'geojson',
      'data': geoPoints_JSON,
    });

    map.addLayer({
        'id': 'region-fill',
        'type': 'fill',
        'source': "region-boundaries",
        'layout': {},
        'paint': {
            'fill-color': '#C4633F',
            'fill-opacity': 0.5
        },
        "filter": ["==", "$type", "Polygon"]
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

错误是:

Uncaught Error: Style is not done loading
    at t._checkLoaded (mapbox-gl.js:308)
    at t.addSource (mapbox-gl.js:308)
    at e.addSource (mapbox-gl.js:390)
    at map.js:92 (map.addSource("region-boundaries",...)
    at XMLHttpRequest.xobj.onreadystatechange (map.js:63)
Run Code Online (Sandbox Code Playgroud)

为什么loadRegionMask()在测试加载样式后调用却出现此错误?

Nat*_*lur 7

好吧,这个地图框问题很糟糕,但我有一个解决方案

myMap.on('styledata', () => {
  const waiting = () => {
    if (!myMap.isStyleLoaded()) {
      setTimeout(waiting, 200);
    } else {
      loadMyLayers();
    }
  };
  waiting();
});
Run Code Online (Sandbox Code Playgroud)

我混合了两种解决方案。


hij*_*tao 6

1.听styledata事件解决你的问题

您可能需要styledata在您的项目中监听事件,因为这是 mapbox-gl-js 文档中提到的唯一标准事件,请参阅https://docs.mapbox.com/mapbox-gl-js/api/#map.event:样式数据

你可以这样使用它:

map.on('styledata', function() {
    addLayer();
});
Run Code Online (Sandbox Code Playgroud)

2. 不应该使用上述其他方法的原因

  1. setTimeout 可能有效,但不是解决问题的推荐方法,如果渲染工作繁重,您会得到意想不到的结果;
  2. style.load是 mapbox 中的私人事件,如 issue https://github.com/mapbox/mapbox-gl-js/issues/7579 中所述,所以我们显然不应该听它;
  3. .isStyleLoaded() 工作但不能一直调用直到样式满载,你需要一个监听器而不是一个判断方法;

  • 我发现“mapbox-gl 1.1.1”在没有修改的情况下不起作用:“styledata”事件被多次触发,因此我在尝试重新添加已存在的图层时遇到错误。我还需要创建一个布尔标志来跟踪图层是否已添加:每当样式更改时,它设置为“false”,当调用“addLayer()”时,它设置为“true”。这非常hackish,但似乎是必要的。 (3认同)

Bwy*_*yss 3

我遇到了类似的问题,最终得到了这个解决方案:

我创建了一个小函数来检查样式是否已完成加载:

// Check if the Mapbox-GL style is loaded.
function checkIfMapboxStyleIsLoaded() {
  if (map.isStyleLoaded()) {
    return true; // When it is safe to manipulate layers
  } else {
    return false; // When it is not safe to manipulate layers
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,每当我交换或以其他方式修改应用程序中的图层时,我都会使用如下函数:

function swapLayer() {
  var check = checkIfMapboxStyleIsLoaded();
  if (!check) {
    // It's not safe to manipulate layers yet, so wait 200ms and then check again
    setTimeout(function() {
      swapLayer();
    }, 200);
    return;
  }

  // Whew, now it's safe to manipulate layers!
  the rest of the swapLayer logic goes here...

}
Run Code Online (Sandbox Code Playgroud)