(Needs to run locally or use the raw version to see leaflet hash)
Animated gif:
Built with blockbuilder.org
forked from enjalot's block: WWSD #1: Leaflet starter
license: mit |
(Needs to run locally or use the raw version to see leaflet hash)
Animated gif:
Built with blockbuilder.org
forked from enjalot's block: WWSD #1: Leaflet starter
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" /> | |
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script> | |
<script src="leaflet-hash.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
#map { | |
height: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<script> | |
var map = L.map('map').setView([30, 0], 2); | |
L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', { | |
attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data © <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>' | |
}).addTo(map); | |
L.control.scale().addTo(map); | |
var hash = new L.Hash(map); | |
</script> | |
</body> |
(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.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; | |
} | |
}; | |
L.Hash.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("/"); | |
}, | |
L.Hash.prototype = { | |
map: null, | |
lastHash: null, | |
parseHash: L.Hash.parseHash, | |
formatHash: L.Hash.formatHash, | |
init: function(map) { | |
this.map = map; | |
// reset the hash | |
this.lastHash = null; | |
this.onHashChange(); | |
if (!this.isListening) { | |
this.startListening(); | |
} | |
}, | |
removeFrom: function(map) { | |
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.removeFrom(); | |
}; | |
})(window); |