Display Raster Tiles in Leaflet
Basic Map
This example adds Maptoolkit raster tiles as a tile layer to a Leaflet map:
let map = L.map("map").setView([47.310897, 12.805988], 12);
L.tileLayer("https://rtc-cdn.maptoolkit.net/rtc/maptoolkit-maptoolkit.summer/{z}/{x}/{y}{ratio}.png?api_key=YOUR_API_KEY", {
ratio: L.Browser.retina ? "@2x" : "",
maxZoom: 18,
attribution:
"© <a href='https://www.maptoolkit.com' target='_blank'>Maptoolkit</a> \
© <a href='https://www.openstreetmap.org/copyright' target='_blank'>OSM</a>",
}).addTo(map);<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css" />
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
let map = L.map("map").setView([47.310897, 12.805988], 12);
L.tileLayer("https://rtc-cdn.maptoolkit.net/rtc/maptoolkit-maptoolkit.summer/{z}/{x}/{y}{ratio}.png?api_key=YOUR_API_KEY", {
ratio: L.Browser.retina ? "@2x" : "",
maxZoom: 18,
attribution:
"© <a href='https://www.maptoolkit.com' target='_blank'>Maptoolkit</a> \
© <a href='https://www.openstreetmap.org/copyright' target='_blank'>OSM</a>",
}).addTo(map);
</script>
</body>
</html>Switching Styles
Each Standard Map Style is its own raster endpoint, so you can offer several
styles through a Leaflet layer control. Add one L.tileLayer per style and pass
them to L.control.layers as base layers:
const attribution =
"© <a href='https://www.maptoolkit.com' target='_blank'>Maptoolkit</a> \
© <a href='https://www.openstreetmap.org/copyright' target='_blank'>OSM</a>";
// Build a raster tile layer for one of the Standard Map Styles.
// `name` is the maptoolkit-maptoolkit.<variant> id.
function style(name) {
return L.tileLayer(
"https://rtc-cdn.maptoolkit.net/rtc/" + name + "/{z}/{x}/{y}{ratio}.png?api_key=YOUR_API_KEY",
{ ratio: L.Browser.retina ? "@2x" : "", maxZoom: 18, attribution: attribution }
);
}
const baseLayers = {
"Summer": style("maptoolkit-maptoolkit.summer"),
"Winter": style("maptoolkit-maptoolkit.winter"),
"Hiking": style("maptoolkit-maptoolkit.hiking"),
"Cycling": style("maptoolkit-maptoolkit.cycling"),
"Street": style("maptoolkit-maptoolkit.street"),
"Light": style("maptoolkit-maptoolkit.light"),
"Dark": style("maptoolkit-maptoolkit.dark"),
};
const map = L.map("map", {
center: [47.310897, 12.805988],
zoom: 12,
layers: [baseLayers["Summer"]],
});
L.control.layers(baseLayers, null, { collapsed: false }).addTo(map);<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css" />
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const attribution =
"© <a href='https://www.maptoolkit.com' target='_blank'>Maptoolkit</a> \
© <a href='https://www.openstreetmap.org/copyright' target='_blank'>OSM</a>";
// Build a raster tile layer for one of the Standard Map Styles.
// `name` is the maptoolkit-maptoolkit.<variant> id.
function style(name) {
return L.tileLayer(
"https://rtc-cdn.maptoolkit.net/rtc/" + name + "/{z}/{x}/{y}{ratio}.png?api_key=YOUR_API_KEY",
{ ratio: L.Browser.retina ? "@2x" : "", maxZoom: 18, attribution: attribution }
);
}
const baseLayers = {
"Summer": style("maptoolkit-maptoolkit.summer"),
"Winter": style("maptoolkit-maptoolkit.winter"),
"Hiking": style("maptoolkit-maptoolkit.hiking"),
"Cycling": style("maptoolkit-maptoolkit.cycling"),
"Street": style("maptoolkit-maptoolkit.street"),
"Light": style("maptoolkit-maptoolkit.light"),
"Dark": style("maptoolkit-maptoolkit.dark"),
};
const map = L.map("map", {
center: [47.310897, 12.805988],
zoom: 12,
layers: [baseLayers["Summer"]],
});
L.control.layers(baseLayers, null, { collapsed: false }).addTo(map);
</script>
</body>
</html>How it works
Leaflet renders pre-rendered PNG images, so there is no style JSON and no WebGL. The tile
URL carries everything: the style id, the {z}/{x}/{y} position and your api_key.
{ratio} is a Maptoolkit placeholder rather than a Leaflet one, which is why it is paired
with the ratio option. L.Browser.retina ? "@2x" : "" fills it with @2x on high-density
screens and an empty string elsewhere, so the same URL serves both. Drop the option and the
literal text {ratio} ends up in the request.
Attribution is your job here. A vector style JSON carries an attribution string that
the library displays on its own; a raster tile URL carries nothing. Leaving the
attribution option out produces a map with no credit, which the license does not allow.
The style switcher builds one L.tileLayer per style and hands them to
L.control.layers. The ids follow maptoolkit-maptoolkit.<variant>, and the seven variants
are summer, winter, hiking, cycling, street, light and dark.
Leaflet takes [latitude, longitude], the opposite order from MapLibre and Mapbox GL JS.
Next steps
With the basemap working, the next move is your data on top. Leaflet handles that with
L.geoJSON, L.marker and L.polyline, none of which care that the tiles underneath are
raster.
The style switcher above is also the shape of a more useful control than it looks. Summer, Winter, Hiking and Cycling are genuinely different maps rather than palettes, so letting a user pick is worth doing on anything outdoor. If you later need to restyle rather than swap, that is the point to move to Vector Tiles, which restyle on the client.