Skip to content

Instantly share code, notes, and snippets.

@rclark
Last active December 18, 2015 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rclark/5811591 to your computer and use it in GitHub Desktop.
Save rclark/5811591 to your computer and use it in GitHub Desktop.
Leaflet + Github-hosted vector-tiles
<!DOCTYPE html>
<html lang="en" style="height:100%; width:100%; padding:0; margin:0;">
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.2/leaflet.css">
</head>
<body style="height:100%; width:100%; padding:0; margin:0;">
<div id="map" style="height:100%; width:100%; padding:0; margin:0;"></div>
<script src="http://cdn.leafletjs.com/leaflet-0.6.2/leaflet.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="https://rawgithub.com/bjornharrtell/jsts/master/lib/javascript.util.js"></script>
<script src="https://rawgithub.com/bjornharrtell/jsts/master/lib/jsts.js"></script>
<script src="L.TileLayer.GeoJSON.js"></script>
<script>
var baseLayer = new L.TileLayer("http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg"),
polyLayer = new L.TileLayer.GeoJSON(
"https://rawgithub.com/rclark/happy-valley-tiles/master/geopolys/{z}/{x}/{y}.geojson",
{
//idAttr: "mapunitpolys_id" // uncomment this and it will merge polys across boundaries
}
)
var map = new L.Map("map", {
center: new L.LatLng(32.1855, -110.4356),
zoom: 12,
layers: [baseLayer, polyLayer]
});
</script>
</body>
</html>
/* If you haven't included JSTS, it'll still work, but won't try and merge features
* across tile boundaries. You DO have to include:
* jQuery
*/
var jsts = jsts || null;
L.Cache = L.GeoJSON.extend({
mergeData: function mergeData(geojson) {
var self = this;
function addFeatures(geodata) {
L.GeoJSON.prototype.addData.call(self, geodata);
}
var pkField = this.options.idAttr;
if (pkField != null && jsts != null) {
var reader = new jsts.io.GeoJSONReader(),
writer = new jsts.io.GeoJSONWriter(),
newFeatures = [];
this.existingFeatures = existingFeatures = this.existingFeatures || {};
function removeLayer(pk) {
for (layerId in self._layers) {
var layer = self._layers[layerId];
if (layer.feature.properties[pkField] == pk) {
self.removeLayer(layer);
return;
}
}
}
function processFeature(feature, index, array) {
var pk = feature.properties[pkField];
if (pk in existingFeatures) {
var addGeom = reader.read(feature.geometry),
oldGeom = reader.read(existingFeatures[pk].geometry),
newGeom = oldGeom.union(addGeom);
feature.geometry = writer.write(newGeom);
removeLayer(pk);
}
existingFeatures[pk] = feature;
newFeatures.push(feature);
counter--;
if (counter == 0) {
addFeatures(newFeatures);
}
}
var newData = L.Util.isArray(geojson) ? geojson : geojson.features || [geojson],
counter = newData.length;
newData.forEach(processFeature);
}
else {
addFeatures(geojson);
}
}
});
L.TileLayer.GeoJSON = L.TileLayer.extend({
onAdd: function onAdd(map) {
var refresh = this.refreshCache,
cacheOpts = {
pointToLayer: this.options.pointToLayer || function () {},
style: this.options.style || function () {},
onEachFeature: this.options.onEachFeature || function () {},
filter: this.options.filter || function () { return true; },
idAttr: this.options.idAttr || null
};
this._cache = new L.Cache(null, cacheOpts);
this._cache.addTo(map);
L.TileLayer.prototype.onAdd.call(this, map);
this.on("tileunload", function unloadTile(d) {
d.tile.xhr.abort();
d.tile.chr = null;
});
var self = this;
map.on("zoomend", function zoomEnd(event) {
map.removeLayer(self._cache);
self._cache = new L.Cache(null, cacheOpts);
self._cache.addTo(map);
});
},
_loadTile: function loadTile(tile, tilePoint) {
var self = this;
this._adjustTilePoint(tilePoint);
if (!tile.xhr) {
tile.xhr = $.ajax({
url: self.getTileUrl(tilePoint),
success: function ajaxSuccess(geojson) {
try { geojson = JSON.parse(geojson); } catch(err) {}
self._cache.mergeData(geojson);
}
});
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment