Data from:
Last active
December 18, 2015 13:18
-
-
Save NelsonMinar/5788481 to your computer and use it in GitHub Desktop.
Rivers: search + Stamen terrain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.leaflet-control-geocoder a { | |
background-position: 50% 50%; | |
background-repeat: no-repeat; | |
display: block; | |
} | |
.leaflet-control-geocoder { | |
box-shadow: 0 1px 7px #999; | |
background: #f8f8f9; | |
-moz-border-radius: 8px; | |
-webkit-border-radius: 8px; | |
border-radius: 8px; | |
} | |
.leaflet-control-geocoder a { | |
background-image: url(images/geocoder.png); | |
width: 36px; | |
height: 36px; | |
} | |
.leaflet-touch .leaflet-control-geocoder a { | |
width: 44px; | |
height: 44px; | |
} | |
.leaflet-control-geocoder .leaflet-control-geocoder-form, | |
.leaflet-control-geocoder-expanded .leaflet-control-geocoder-toggle { | |
display: none; | |
} | |
.leaflet-control-geocoder-expanded .leaflet-control-geocoder-form { | |
display: block; | |
position: relative; | |
} | |
.leaflet-control-geocoder-expanded .leaflet-control-geocoder-form { | |
padding: 5px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
L.Control.NominatimGeocoder = L.Control.extend({ | |
options: { | |
collapsed: true, | |
position: 'topright', | |
text: 'Locate', | |
callback: function (results) { | |
// Check if no results are returned | |
if (results.length >= 1) { | |
// Just take the first place | |
var bbox = results[0].boundingbox, | |
southWest = new L.LatLng(bbox[0], bbox[2]), | |
northEast = new L.LatLng(bbox[1], bbox[3]), | |
bounds = new L.LatLngBounds(southWest, northEast); | |
// Center on it | |
this._map.fitBounds(bounds); | |
} | |
// TODO Indicate lack of results to user | |
} | |
}, | |
_callbackId: 0, | |
initialize: function (options) { | |
L.Util.setOptions(this, options); | |
}, | |
onAdd: function (map) { | |
this._map = map; | |
var className = 'leaflet-control-geocoder', | |
container = this._container = L.DomUtil.create('div', className); | |
L.DomEvent.disableClickPropagation(container); | |
var form = this._form = L.DomUtil.create('form', className + '-form'); | |
var input = this._input = document.createElement('input'); | |
input.type = "text"; | |
var submit = document.createElement('button'); | |
submit.type = "submit"; | |
submit.innerHTML = this.options.text; | |
form.appendChild(input); | |
form.appendChild(submit); | |
L.DomEvent.addListener(form, 'submit', this._geocode, this); | |
if (this.options.collapsed) { | |
L.DomEvent.addListener(container, 'mouseover', this._expand, this); | |
L.DomEvent.addListener(container, 'mouseout', this._collapse, this); | |
var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); | |
link.href = '#'; | |
link.title = 'Nominatim Geocoder'; | |
L.DomEvent.addListener(link, L.Browser.touch ? 'click' : 'focus', this._expand, this); | |
this._map.on('movestart', this._collapse, this); | |
} else { | |
this._expand(); | |
} | |
container.appendChild(form); | |
return container; | |
}, | |
_geocode : function (event) { | |
L.DomEvent.preventDefault(event); | |
this._callbackId = "_l_nominatimgeocoder_" + (this._callbackId++); | |
window[this._callbackId] = L.Util.bind(this.options.callback, this); | |
var params = { | |
q: this._input.value, | |
format: "json", | |
// We only use the first result currently | |
limit: 1, | |
json_callback : this._callbackId | |
}, | |
url = "http://open.mapquestapi.com/nominatim/v1/search" + L.Util.getParamString(params), | |
script = document.createElement("script"); | |
script.type = "text/javascript"; | |
script.src = url; | |
script.id = this._callbackId; | |
document.getElementsByTagName("head")[0].appendChild(script); | |
}, | |
_expand: function () { | |
L.DomUtil.addClass(this._container, 'leaflet-control-geocoder-expanded'); | |
}, | |
_collapse: function () { | |
this._container.className = this._container.className.replace(' leaflet-control-geocoder-expanded', ''); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"><head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0"/> | |
<title>Leaflet vector tile map of rivers</title> | |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" /> | |
<link rel="stylesheet" href="Control.NominatimGeocoder.css" /> | |
<script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script> | |
<script src="leaflet-hash.js"></script> | |
<script src="Control.NominatimGeocoder.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="TileLayer.d3_geoJSON.js"></script> | |
<style type="text/css"> | |
html, body { height: 100% } | |
#map { min-height: 100%; } | |
body { | |
margin: 0; | |
font-family: Helvetica Neue, Helvetica, Arial, sans-serif; font-size: 12px; | |
overflow: hidden; | |
background-color: #f00; | |
} | |
.leaflet-popup-content-wrapper { | |
-webkit-border-radius: 5px; | |
border-radius: 5px; | |
} | |
path { stroke-linejoin; round; stroke-linecap: round; fill: none; } | |
path.river { stroke: #29439c; } | |
</style> | |
</head><body> | |
<div id="map"></div> | |
<script type="text/javascript"> | |
// Construct map, center if no location provided | |
var map = L.map('map', { maxZoom: 18 } ); | |
var hash = new L.Hash(map); | |
if (!window.location.hash) { | |
map.setView([37.958, -120.976], 8); | |
} | |
// Add Nominatim search | |
var geocoder = new L.Control.NominatimGeocoder({"collapsed": false}); | |
map.addControl(geocoder); | |
// Fake GeoJSON line to make Leaflet create the <svg> tag that d3_geoJson needs | |
new L.geoJson({"type": "LineString","coordinates":[[0,0],[0,0]]}).addTo(map); | |
// Make the base map | |
var baseUrl = 'http://{s}.tile.stamen.com/terrain/{z}/{x}/{y}.png'; | |
var basemap = L.tileLayer(baseUrl, { | |
attribution: '<a href="http://maps.stamen.com/">Stamen base map</a>, <a href="http://www.horizon-systems.com/NHDPlus/NHDPlusV2_home.php">NHDPlus v2</a>, <a href="http://www.mapquest.com/" target="_blank">MapQuest Nominatim</a>', | |
maxZoom: 20 | |
}); | |
basemap.addTo(map); | |
// Style the river lines; width depends on its Strahler number | |
function riverStyle(feature) { | |
return "stroke-width: " + feature.properties.strahler * map.getZoom()/13 + "px;"; | |
} | |
// Make the river overlay layer, vector tiles from our TileStache/Gunicorn server | |
var geojsonURL = "http://www.somebits.com:8001/rivers/{z}/{x}/{y}.json"; | |
var riverLayer = new L.TileLayer.d3_geoJSON(geojsonURL, { | |
class: "river", | |
style: riverStyle, | |
}); | |
map.addLayer(riverLayer); | |
</script> | |
</body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(window) { | |
var HAS_HASHCHANGE = (function() { | |
var doc_mode = window.documentMode; | |
return ('onhashchange' in window) && | |
(doc_mode === undefined || doc_mode > 7); | |
})(); | |
L.Hash = function(map) { | |
this.onHashChange = L.Util.bind(this.onHashChange, this); | |
if (map) { | |
this.init(map); | |
} | |
}; | |
L.Hash.prototype = { | |
map: null, | |
lastHash: null, | |
parseHash: function(hash) { | |
if(hash.indexOf('#') === 0) { | |
hash = hash.substr(1); | |
} | |
var args = hash.split("/"); | |
if (args.length == 3) { | |
var zoom = parseInt(args[0], 10), | |
lat = parseFloat(args[1]), | |
lon = parseFloat(args[2]); | |
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) { | |
return false; | |
} else { | |
return { | |
center: new L.LatLng(lat, lon), | |
zoom: zoom | |
}; | |
} | |
} else { | |
return false; | |
} | |
}, | |
formatHash: function(map) { | |
var center = map.getCenter(), | |
zoom = map.getZoom(), | |
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)); | |
return "#" + [zoom, | |
center.lat.toFixed(precision), | |
center.lng.toFixed(precision) | |
].join("/"); | |
}, | |
init: function(map) { | |
this.map = map; | |
// reset the hash | |
this.lastHash = null; | |
this.onHashChange(); | |
if (!this.isListening) { | |
this.startListening(); | |
} | |
}, | |
remove: function() { | |
if (this.changeTimeout) { | |
clearTimeout(this.changeTimeout); | |
} | |
if (this.isListening) { | |
this.stopListening(); | |
} | |
this.map = null; | |
}, | |
onMapMove: function() { | |
// bail if we're moving the map (updating from a hash), | |
// or if the map is not yet loaded | |
if (this.movingMap || !this.map._loaded) { | |
return false; | |
} | |
var hash = this.formatHash(this.map); | |
if (this.lastHash != hash) { | |
location.replace(hash); | |
this.lastHash = hash; | |
} | |
}, | |
movingMap: false, | |
update: function() { | |
var hash = location.hash; | |
if (hash === this.lastHash) { | |
return; | |
} | |
var parsed = this.parseHash(hash); | |
if (parsed) { | |
this.movingMap = true; | |
this.map.setView(parsed.center, parsed.zoom); | |
this.movingMap = false; | |
} else { | |
this.onMapMove(this.map); | |
} | |
}, | |
// defer hash change updates every 100ms | |
changeDefer: 100, | |
changeTimeout: null, | |
onHashChange: function() { | |
// throttle calls to update() so that they only happen every | |
// `changeDefer` ms | |
if (!this.changeTimeout) { | |
var that = this; | |
this.changeTimeout = setTimeout(function() { | |
that.update(); | |
that.changeTimeout = null; | |
}, this.changeDefer); | |
} | |
}, | |
isListening: false, | |
hashChangeInterval: null, | |
startListening: function() { | |
this.map.on("moveend", this.onMapMove, this); | |
if (HAS_HASHCHANGE) { | |
L.DomEvent.addListener(window, "hashchange", this.onHashChange); | |
} else { | |
clearInterval(this.hashChangeInterval); | |
this.hashChangeInterval = setInterval(this.onHashChange, 50); | |
} | |
this.isListening = true; | |
}, | |
stopListening: function() { | |
this.map.off("moveend", this.onMapMove, this); | |
if (HAS_HASHCHANGE) { | |
L.DomEvent.removeListener(window, "hashchange", this.onHashChange); | |
} else { | |
clearInterval(this.hashChangeInterval); | |
} | |
this.isListening = false; | |
} | |
}; | |
L.hash = function(map) { | |
return new L.Hash(map); | |
}; | |
L.Map.prototype.addHash = function() { | |
this._hash = L.hash(this); | |
}; | |
L.Map.prototype.removeHash = function() { | |
this._hash.remove(); | |
}; | |
})(window); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Experimental vector tile layer for Leaflet | |
* Uses D3 to render GeoJSON; faster than Leaflet's native. | |
* Originally by Ziggy Jonsson: http://bl.ocks.org/ZJONSSON/5602552 | |
* Reworked by Nelson Minar: http://bl.ocks.org/NelsonMinar/5624141 | |
* | |
* While working (and fast!) this plugin requires work to work like | |
* a typical Leaflet layer. Todo: | |
* Make this work even if <svg> isn't in the DOM yet; | |
* For now, add a fake GeoJSON layer to your map before one of these | |
* new L.geoJson({"type":"LineString","coordinates":[[0,0],[0,0]]}).addTo(map); | |
* Make this work for tile types that aren't FeatureCollection | |
* Match D3 idioms for .classed(), .style(), etc? Or match the Leaflet API? | |
* Work on allowing feature popups, etc. | |
*/ | |
L.TileLayer.d3_geoJSON = L.TileLayer.extend({ | |
onAdd : function(map) { | |
L.TileLayer.prototype.onAdd.call(this,map); | |
this._path = d3.geo.path().projection(function(d) { | |
var point = map.latLngToLayerPoint(new L.LatLng(d[1],d[0])); | |
return [point.x,point.y]; | |
}); | |
this.on("tileunload",function(d) { | |
if (d.tile.xhr) d.tile.xhr.abort(); | |
if (d.tile.nodes) d.tile.nodes.remove(); | |
d.tile.nodes = null; | |
d.tile.xhr = null; | |
}); | |
}, | |
_loadTile : function(tile,tilePoint) { | |
var self = this; | |
this._adjustTilePoint(tilePoint); | |
if (!tile.nodes && !tile.xhr) { | |
tile.xhr = d3.json(this.getTileUrl(tilePoint),function(geoJson) { | |
tile.xhr = null; | |
tile.nodes = d3.select(map._container).select("svg").append("g"); | |
tile.nodes.selectAll("path") | |
.data(geoJson.features).enter() | |
.append("path") | |
.attr("d", self._path) | |
.attr("class", self.options.class) | |
.attr("style", self.options.style); | |
}); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment