So I already ask this on stackoverflow without getting an answer: http://stackoverflow.com/questions/38631344/recommended-way-to-switch-tile-urls-in-mapbox-gl-js
We render a raster layer to the map. The layer's source has an initial tile url. Now we want to change the tile url of the source and trigger a reload for the new tiles.
E.g.: We have tiles for different points in time and we want to step through the different time steps.
[email protected]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();
This works fine. But, of course, using private methods is bad practice; see the reason below:
_(Latest commit 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();
It has to be done this way, because the former TilePyramid has been refactored to a SourceCache. Here we are calling reload() on the SourceCache not the RasterTileSource. It seems that we don't have to use any private methods anymore, though this still looks like undocumented API, which may break in future versions.
Also there seems to be an issue with a memory leak when calling reload(): #2266
Additionally the cache gets cleared when calling reload(). Which for now doesn't seem to be an issue.
What is the recommended way to do something like this? Is this a feature being worked on? Is there an explanation why this isn't a feature (yet) or never will be?
Thank you for using GL JS. Due to the large volume of issues we get and the relatively small size of our team, we are unable to provide support here on GitHub. I have responded to your question on SO.
...can be done with the current version from github
_(Latest commit 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();It has to be done this way, because the former ....
source url from map.getStyle().sources not updated after reload()
any best practices for this method or official api to update source tile/url?
Note that the solutions mentioned earlier here no longer works. Instead, use this:
// Set the tile url to a cache-busting url (to circumvent browser caching behaviour):
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()
This causes the layer(s) that depend upon the source to visually flash/dissappear for a moment. This is a clear indication it is working, but this could be a bit annoying if these reloads happen often. This happens because the sourceCache is empty while the new tiles are being fetched. (update is asynchronous)
A solution that avoids this "flicker" might be creating a new source, letting it load the new tiles in the background, before somehow switching.
Most helpful comment
Current solution
Note that the solutions mentioned earlier here no longer works. Instead, use this:
NOTE
This causes the layer(s) that depend upon the source to visually flash/dissappear for a moment. This is a clear indication it is working, but this could be a bit annoying if these reloads happen often. This happens because the sourceCache is empty while the new tiles are being fetched. (update is asynchronous)
A solution that avoids this "flicker" might be creating a new source, letting it load the new tiles in the background, before somehow switching.