Skip to content

Add tile sources

Drawing a tile endpoint takes two style objects: a source that describes where the tiles are and how to read them, and a layer that draws them. Both belong to the loaded style. Add them after a style-loaded event and again after every later style load, as Load a style describes.

How you describe the source depends on what the server publishes. MapLibre reads tile URLs and properties from a TileJSON document. For other servers, supply the tile URLs and properties directly.

Pass the document URL and use the default options when the server publishes a TileJSON document. MapLibre reads the tile URLs, zoom range, scheme, bounds, and attribution. Then add a layer that names the source.

tile-source-tilejson.c
const mln_status status = mln_map_add_vector_source_url(
map, view("basemap"), view("https://tiles.example.com/planet/tiles.json"),
NULL
);
if (status != MLN_STATUS_OK) {
return status;
}
return add_layer(map);

Options can override the document’s zoom range and encoding. They can also override the tile size for raster and raster-DEM sources. Vector tiles decode as MVT by default. Select MapLibre Tiles for that encoding. MapLibre Tiles data with FastPFOR integer streams also requires the FastPFOR map option.

A vector tile carries several named layers. A layer that draws one of them sets source to the source ID and source-layer to the name inside the tile.

tile-source-tilejson.c
const char layer[] =
"{\"id\":\"roads\",\"type\":\"line\",\"source\":\"basemap\","
"\"source-layer\":\"transportation\"}";

Supply URL templates when the server has no TileJSON document. Each template contains the {z}, {x}, and {y} placeholders. MapLibre fills them for each tile. Several templates with different host names distribute requests among those hosts.

tile-source-templates.c
const mln_buffer_view tiles[] = {
view("https://a.tiles.example.com/ortho/{z}/{x}/{y}.png"),
view("https://b.tiles.example.com/ortho/{z}/{x}/{y}.png"),
};

Set only the options that the server requires.

tile-source-templates.c
mln_style_tile_source_options options =
mln_style_tile_source_options_default();
options.fields = MLN_STYLE_TILE_SOURCE_OPTION_MAX_ZOOM |
MLN_STYLE_TILE_SOURCE_OPTION_TILE_SIZE |
MLN_STYLE_TILE_SOURCE_OPTION_BOUNDS |
MLN_STYLE_TILE_SOURCE_OPTION_ATTRIBUTION;
options.max_zoom = 19;
// 256 suits classic slippy tiles, and the default is 512.
options.tile_size = 256;

Bounds limit requests to the area that the server covers, and the zoom range limits them to the available levels. The source retains the attribution string for later reads. The default XYZ scheme numbers rows from the north; use TMS for a server that numbers rows from the south.

tile-source-templates.c
options.bounds = (mln_lat_lng_bounds){
.southwest = {.latitude = 47.2, .longitude = 5.8},
.northeast = {.latitude = 55.1, .longitude = 15.1},
};
options.attribution = view("Imagery: Example Survey");

Pass the templates and the options to the call that adds a raster source, then add a raster layer that names the source.

tile-source-templates.c
const mln_status status = mln_map_add_raster_source_tiles(
map, view("ortho"), tiles, sizeof(tiles) / sizeof(tiles[0]), &options
);
if (status != MLN_STATUS_OK) {
return status;
}
return add_layer(map);

Raster-DEM tiles encode elevation in their color channels as Mapbox Terrain-RGB or Terrarium. Mapbox Terrain-RGB is the default. Select the encoding that the server publishes to obtain the correct elevations.

tile-source-raster-dem.c
mln_style_tile_source_options options =
mln_style_tile_source_options_default();
options.fields = MLN_STYLE_TILE_SOURCE_OPTION_RASTER_ENCODING |
MLN_STYLE_TILE_SOURCE_OPTION_MAX_ZOOM;
options.raster_encoding = MLN_STYLE_RASTER_DEM_ENCODING_TERRARIUM;
options.max_zoom = 12;

A raster-DEM source takes the same tile URL templates as a raster source.

tile-source-raster-dem.c
const mln_buffer_view tiles[] = {
view("https://tiles.example.com/terrain/{z}/{x}/{y}.png"),
};
const mln_status status = mln_map_add_raster_dem_source_tiles(
map, view("terrain"), tiles, sizeof(tiles) / sizeof(tiles[0]), &options
);

A hillshade layer requires a raster-DEM source. The dedicated hillshade-layer call adds it without a JSON layer object.

tile-source-raster-dem.c
// An empty before-layer ID puts the layer on top of the style.
return mln_map_add_hillshade_layer(
map, view("hillshading"), view("terrain"), view("")
);