Change a Layer's Color with Buttons in Maptoolkit Maps JS
Changing a layer’s color at runtime in Maptoolkit Maps JS is done with map.setPaintProperty, which updates any paint property on an existing layer without reloading the style. This example connects a set of buttons to different color values and applies them to a fill layer when clicked. Use this pattern to build theme switchers, highlight modes, or any UI that lets users adjust how data is visualized on the map.
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [13.405, 52.52],
zoom: 14,
attributionControl: { compact: false }
});
const swatches = document.getElementById('swatches');
const layer = document.getElementById('layer');
const colors = [
'#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494',
'#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'
];
colors.forEach((color) => {
const swatch = document.createElement('button');
swatch.style.backgroundColor = color;
swatch.addEventListener('click', () => {
map.setPaintProperty(layer.value, 'fill-color', color);
});
swatches.appendChild(swatch);
});<!DOCTYPE html>
<html lang="en">
<head>
<title>Change a Layer's Color with Buttons - Maptoolkit Maps JS</title>
<meta property="og:description" content="Change the color of a map layer dynamically using buttons." />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#map { width: 100%; height: 100%; }
.map-overlay {
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
position: absolute;
width: 200px;
top: 0;
left: 0;
padding: 10px;
}
.map-overlay .map-overlay-inner {
background-color: #fff;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
border-radius: 3px;
padding: 10px;
margin-bottom: 10px;
}
.map-overlay-inner fieldset {
border: none;
padding: 0;
margin: 0 0 10px;
}
.map-overlay-inner fieldset:last-child {
margin: 0;
}
.map-overlay-inner select {
width: 100%;
}
.map-overlay-inner label {
display: block;
font-weight: bold;
margin: 0 0 5px;
}
.map-overlay-inner button {
display: inline-block;
width: 36px;
height: 20px;
border: none;
cursor: pointer;
}
.map-overlay-inner button:focus {
outline: none;
}
.map-overlay-inner button:hover {
box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div id="map"></div>
<div class="map-overlay top">
<div class="map-overlay-inner">
<fieldset>
<label for="layer">Select layer</label>
<select id="layer" name="layer">
<option value="water">Water</option>
<option value="building_multicolored">Buildings</option>
</select>
</fieldset>
<fieldset>
<label>Choose a color</label>
<div id="swatches"></div>
</fieldset>
</div>
</div>
<script>
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [13.405, 52.52],
zoom: 14,
attributionControl: { compact: false }
});
const swatches = document.getElementById('swatches');
const layer = document.getElementById('layer');
const colors = [
'#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494',
'#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'
];
colors.forEach((color) => {
const swatch = document.createElement('button');
swatch.style.backgroundColor = color;
swatch.addEventListener('click', () => {
map.setPaintProperty(layer.value, 'fill-color', color);
});
swatches.appendChild(swatch);
});
</script>
</body>
</html>Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.
How it works
setPaintProperty changes a paint value on a layer that already exists. Nothing reloads: the
style stays, the data stays, and only the property is re-evaluated, which is why this is
instant where reloading a style would flash.
The layer id has to exist in the current style. Ids differ between our seven styles, so a
hard-coded id that works on summer may not exist on dark, and setting a property on a
missing layer throws.
The paint property name has to match the layer type: fill-color on a fill layer,
line-color on a line layer. Setting fill-color on a line layer is a silent no-op.
setLayoutProperty is the counterpart for layout properties such as visibility and
text-field. Layout changes are more expensive than paint changes, because they can force a
relayout of labels.
Next steps
Runtime restyling is most useful when it is not arbitrary. Driving the colour from the data rather than a button turns the same mechanism into a choropleth, and the buttons become a choice of which property to colour by.
The other common use is a light and dark mode, which usually means swapping the whole style rather than one layer. Vector Tiles lists the Light and Dark variants, which is less work than recolouring layer by layer.