在mapbox-gl-js中切换瓦片URL的推荐方法是什么?

10

情境

我们在地图上呈现一个光栅(raster)图层。该图层的源具有初始瓦片URL。现在我们想要更改源的瓷砖URL并触发新瓷砖的重新加载。例如,我们有不同时间点的瓷砖,我们想要浏览不同的时间步骤。

mapbox-gl@0.21.0中可以做什么

map.addSource('tile-source', {...});
map.addLayer('tile-layer', {source: 'tile-source', ...});

// react to a button click or what ever to trigger tile url change
...
const source = map.getSource('tile-source');
source.tiles = ['new-tile-url'];
source._pyramid.reload();

这个可以正常工作。但是,当然使用私有方法是不好的做法。请看下面的原因:
当前版本(最新提交b155118,2016-07-28)可以做什么。
// init map, add layer, add source, like above
const source = map.getSource('tile-source');
source.tiles = ['new-tile-url'];

map.styles.sources['tile-source'].reload();

这样做是因为之前的TilePyramid已被重构为一个SourceCache。在这里,我们对SourceCache而不是RasterTileSource调用reload()。似乎我们不再需要使用任何私有方法,但仍然看起来像是未记录的API,可能会在未来版本中发生变化。
此外,在调用reload()时似乎存在内存泄漏问题: https://github.com/mapbox/mapbox-gl-js/issues/2266 此外,调用reload()时缓存将被清除。目前看来这不是一个问题。
// This yields a `RasterTileSource` instance
map.getSource('tile-source'); 

// This yields a `SourceCache` instance
map.styles.sources['tile-source'];

// What's really confusing too, at least namingwise
map.getStyle(); // <-- Yields the maps (visual) style

SourceCache 有一个私有的 _source 字段,其实例是 RasterTileSource

问题

做类似这样的事情推荐使用什么方法?这是正在开发的功能吗?有没有解释为什么这不是一个功能(但可能会成为一个功能)?


如果您的目标是依次显示不同的瓷砖,为什么不保留所有源,并只是玩弄层的“可见性”属性呢? - PhilippeAuriach
3个回答

8

看起来你正在尝试更改raster源的URL。在GL JS中正确的做法是删除该源,然后使用相同的ID和新的URL添加一个新的源。

map.addSource('tile-source', {...});
map.addLayer('tile-layer', {source: 'tile-source', ...});

// react to a button click or what ever to trigger tile url change
...
map.removeSource('tile-source');
map.addSource('tile-source', {tiles: ['new-tile-url'], ...});

谢谢,我们会尝试。 - Scarysize
1
我经常在这样做时看到“源已存在”的错误。我希望有一个像source.setTiles(['https://...'])这样的设置器,它与GeoJSON图层的source.setData更加协调。 - alphabetasoup
1
当您认为已经删除源代码,但实际上某些图层仍在使用它时,您可能会看到“源已存在”错误。请确保没有任何图层在使用您的源代码,然后通过map.removeSource将其删除。 - Andrew

5

这里有另一种方法可以在不删除和添加源和图层的情况下更改Mapbox GL JS图层URL。

// Set the tile URL to a cache-busting URL (to circumvent browser caching behavior):
map.getSource('source-id').tiles = [ `http://some.url/{z}/{x}/{y}.pbf?dt=${Date.now()}` ]

// Remove the tiles for a particular source
map.style.sourceCaches['source-id'].clearTiles()

// Load the new tiles for the current viewport (map.transform -> viewport)
map.style.sourceCaches['source-id'].update(map.transform)

// Force a repaint, so that the map will be repainted without you having to touch the map
map.triggerRepaint()

我已经想出了一个解决方案。不要使用sourceCache,而是使用_sourceCache函数,并在您的id之前输入“other”。

map.style._sourceCaches['other:wms-source'].clearTiles();
map.style._sourceCaches['other:wms-source'].update(map.transform)

https://github.com/mapbox/mapbox-gl-js/issues/2941#issuecomment-518631078


2

Mapbox GL JS v2.13.0于2023年2月22日发布 添加动态更改栅格瓦片源的方法(例如setTiles、setUrl)。 (#12352)

现在,您可以更新栅格源而无需删除图层和源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接