Skip to content

Instantly share code, notes, and snippets.

@reyemtm
Last active December 5, 2023 02:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reyemtm/c93cdc699b06b0b5305a9312efa2282d to your computer and use it in GitHub Desktop.
Save reyemtm/c93cdc699b06b0b5305a9312efa2282d to your computer and use it in GitHub Desktop.
Leaflet Vector Grid with Interactivity

This example uses the latest version of the Leaflet VectorGrid plugin and Leaflet v 1.2 to view highly dense polygon data, in this case parcels. The amount of raw data you can load into the map depends on your usecase. If you are only targeting desktop machines, then a file of 5MB or even 10MB might work. For mobile stick to under 5MB. The plugin uses geojson-vt under the hood to cut geojson or topojson into vector tiles on the fly. This version of the plugin allows for interaction with the data and changing the feature's style on click. See this example for popups and search.

The highlight does not work perfectly, a better way might be to add another layer on top of the parcels with the clicked feature, then remove that layer when another parcel is clicked. Also, due to the nature of vector tiles, more than one feature may be found when clicking on the polygons, so limiting identify to a certain zoom level might make sense, that or looping through all the features.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Leaflet Vector Grid</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.vectorgrid@latest/dist/Leaflet.VectorGrid.bundled.js"></script>
<!--script src="https://getbounds.com/apps-plugins/vectorgrid/leaflet-vector-grid-bundled-working.js"></script-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-omnivore/0.3.4/leaflet-omnivore.min.js" integrity="sha256-k1l+ouvMXT+0iRA8pc8e0dge4ZeGjXG6imrvWboFTRE=" crossorigin="anonymous"></script>
<style>
body {
margin:0;
padding:0;
}
#map {
position:absolute;
top:0;
bottom:0;
width:100%;
}
</style>
</head>
<body>
<div id='map'></div>
<!-- Parcel file for map -->
<script>
// Object to hold our map options
var parcels,
id = 0;
var data = omnivore.topojson('https://reyemtm.github.io/data/topojson/matchewb.parcels.topo.json');
data.on('ready', function() {
parcels = data.toGeoJSON();
buildMap();
});
var options = {
center: [37.95, -122.32],
zoom: 12,
minZoom: 12,
maxZoom: 19,
},
map = L.map('map', options); // Create map object and pass it our options object from above
// load map tiles and add to map
var tiles = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a> | Map Authored by <a href="https://bazini627.github.io/" target="blank">Matthew Bacinskas</a> | <a href="https://getbounds.com">Malcolm Meyer</a>',
subdomains: 'abcd',
maxZoom: 19
}).addTo(map);
map.createPane('parcelPane');
map.getPane('parcelPane').style.zIndex = 650;
function buildMap() {
var tileLayer = L.vectorGrid.slicer(parcels, {
rendererFactory: L.canvas.tile,
vectorTileLayerStyles: {
sliced: {
fillColor: "transparent",
color: "blue",
weight: .5
}
},
maxZoom: 22,
indexMaxZoom: 5, // max zoom in the initial tile index
interactive: true,
getFeatureId: function(feature) {
return feature.properties["cartodb_id"]
}
}).addTo(map);
tileLayer.on('click', function(e) {
console.log(e);
if (e.layer.feature) {
var prop = e.layer.feature.properties;
//var latlng = [e.latlng.lat,e.latlng.lng];
}else {
var prop = e.layer.properties;
//var latlng = [Number(parcel.y),Number(parcel.x)];
}
//settimeout otherwise when map click fires it will override this color change
if (id != 0) {
tileLayer.setFeatureStyle(id, {
color:"blue",
weight: .5,
});
}
id = prop["cartodb_id"];
setTimeout(function() {
tileLayer.setFeatureStyle(id, {
color: "red"
}, 100);
});
});
/* Need to add something to change the style back once another parcel is clicked*/
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment