How to Display High-Performance Vector Tiles from GeoJSON in Leaflet
In this tutorial, we’ll learn how to render large GeoJSON datasets on a Leaflet map using vector tiles generated dynamically via geojson-vt
. This approach offers faster performance, smoother panning/zooming, and canvas rendering for complex layers.
β Why This Matters
Loading raw GeoJSON directly into Leaflet using L.geoJSON()
can get painfully slow with thousands of features. geojson-vt
chunks your data into canvas-rendered vector tiles — just like Mapbox or MapLibre do — but entirely client-side.
Think of it as slicing a pizza into tiles… Leaflet only loads the slice you're eating (viewing).
Download Source Code: Click Here
Watch This Tutorial in Video: Click Here
π§° Prerequisites
-
Basic HTML and JS knowledge
-
GeoJSON data file
-
Leaflet (v1.7+ recommended)
-
jQuery (for document ready)
-
Bootstrap (optional, for layout)
-
geojson-vt
library -
leaflet-geojson-vt
plugin (custom)
ποΈ Folder Structure
project/
β
βββ index.html
βββ data/
β βββ data.js # Contains your GeoJSON as a JS variable
βββ js/
β βββ source_code.js # Leaflet init + geojson-vt logic
β βββ leaflet-geojson-vt.js # Plugin that draws vector tiles on canvas
βββ lib/
β βββ leaflet/
β βββ leaflet.js
β βββ leaflet.css
β βββ leaflet.ajax.min.js
β βββ jquery-3.5.1.js
βββ lib/bootstrap/css/bootstrap.css
π Step-by-Step Implementation
1. HTML Skeleton (index.html
)
Loads Leaflet, Bootstrap, and JS files.
Key imports:
2. GeoJSON Source (data/data.js
)
You must define a global data
variable:
var data = {
"type": "FeatureCollection",
"features": [
// your features here
]
};
3. Vector Tile Plugin (leaflet-geojson-vt.js
)
This custom plugin extends L.GridLayer
and draws vector tiles using canvas
.
Key logic:
createTile: function (coords) {
const tile = L.DomUtil.create("canvas", "leaflet-tile");
...
const features = this.tileIndex.getTile(coords.z, coords.x, coords.y)?.features || [];
features.forEach(f => this.drawFeature(ctx, f));
return tile;
}
4. Map Setup (js/source_code.js
)
myMap = L.map('map_div', {
center:[38.91454,-77.02171],
zoom:12,
zoomControl: false
});
lyrOSM = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(myMap);
var vtLayer = L.geoJson.vt(data, {
maxZoom: 20,
tolerance: 3,
style: {
fillColor: "#F2FF00",
color: "#1EB300",
}
}).addTo(myMap);
β οΈ Common Gotchas
-
No geometry appears? Make sure your GeoJSON
data
variable is loaded before the script runs. -
Tile flickering or overlapping? Set canvas tile size consistently and manage CSS z-index.
-
Too many features per tile? Adjust
maxZoom
,tolerance
, and enabledebug: 1
in options.
π Performance Tips
-
Convert large shapefiles to GeoJSON offline before using.
-
Use
simplify-geojson
or reduce feature count for better zoom responsiveness. -
Explore hybrid client-server approaches later with
pg_tileserv
ortilemaker
.
π‘ Next Enhancements
-
Load GeoJSON from server via AJAX
-
Add dynamic styling by feature properties
-
Add legend and filter controls
-
Use
maplibre-gl
for true vector rendering later
π Conclusion
By using geojson-vt
With Leaflet and a bit of canvas wizardry, you can render huge GeoJSON datasets on the fly — perfect for public dashboards, mobile-first maps, or offline-first apps.
Frequently Asked Questions
A: Vector tiles are small chunks of GeoJSON rendered as canvas tiles, allowing fast map performance in Leaflet even with large datasets.
A: geojson-vt converts GeoJSON to tiled format, enabling smooth zoom and pan without crashing the browser, unlike the basic L.geoJSON approach.
A: Yes, you can load external GeoJSON via AJAX and feed it to geojson-vt dynamically using Leaflet AJAX plugin.
Comments
Leave a Reply