m
maplibre-transition
Animate paint properties per feature
Maintained by Jamie Popkin
A MapLibre GL JS plugin that animates paint properties (radius, color, opacity, width) of individual features through feature state, with easing, delays and multi-step values.
Live demo
maplibre-transition running on MapLibre GL JS in your browser
Loading the map…
Demo code
import MaplibreTransition from "maplibre-transition";
import type { PluginDemo } from "../types";
export default {
center: [12, 50], // Europe
zoom: 3.8,
async run({ map }) {
MaplibreTransition.init(map);
const cities: [string, number, number][] = [
["Lisbon", -9.14, 38.72],
["Madrid", -3.7, 40.42],
["Paris", 2.35, 48.86],
["London", -0.13, 51.51],
["Amsterdam", 4.9, 52.37],
["Berlin", 13.4, 52.52],
["Copenhagen", 12.57, 55.68],
["Stockholm", 18.07, 59.33],
["Warsaw", 21.01, 52.23],
["Vienna", 16.37, 48.21],
["Rome", 12.5, 41.9],
["Athens", 23.73, 37.98],
];
map.addSource("cities", {
type: "geojson",
data: {
type: "FeatureCollection",
features: cities.map(([name, lng, lat], id) => ({
type: "Feature",
id,
properties: { name },
geometry: { type: "Point", coordinates: [lng, lat] },
})),
},
});
map.addLayer({
id: "cities",
type: "circle",
source: "cities",
paint: {
"circle-radius": 2,
"circle-color": "#29335c",
"circle-stroke-color": "#fff",
"circle-stroke-width": 1,
},
});
await map.once("idle");
// Animate each city's paint properties on its own, one after another.
map.queryRenderedFeatures({ layers: ["cities"] }).forEach((feature) => {
map.transition(feature, {
duration: 900,
delay: Number(feature.id) * 150,
ease: "cubic",
paint: { "circle-radius": [2, 16, 9], "circle-color": ["#29335c", "#e4572e"] },
});
});
// And grow a city while the pointer is on it.
map.on(
"mouseenter",
"cities",
(e) =>
e.features?.[0] &&
map.transition(e.features[0], { duration: 300, paint: { "circle-radius": [null, 16] } }),
);
map.on("mouseleave", "cities", () =>
map
.queryRenderedFeatures({ layers: ["cities"] })
.forEach((f) =>
map.transition(f, { duration: 300, paint: { "circle-radius": [null, 9] } }),
),
);
},
} satisfies PluginDemo;