Last active
October 9, 2022 05:39
-
-
Save NelsonMinar/6600524 to your computer and use it in GitHub Desktop.
GTA V Map Viewer
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
Tools for making a very simple web slippy map of Grand Theft Auto V maps. | |
By Nelson Minar <nelson@monkey.org> | |
I don't want to host this map myself because of copyright concerns. | |
No support provided for this code, just hoping it's a useful guide for | |
someone to roll their own amp. | |
maketiles.sh runs gdal2tiles.py to slice up the source image into tiles. | |
map.html is a simple Leaflet / web map. | |
You're on your own for finding the map image source. | |
See this tutorial for more info on gdal2tiles.py | |
http://build-failed.blogspot.com/2012/11/zoomable-image-with-leaflet.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
#!/bin/bash | |
gdal2tiles.py -p raster -z 0-5 -w none GTA\ V\ Map.jpg satellite | |
gdal2tiles.py -p raster -z 0-5 -w none GTA\ V\ Map\ 2.jpg atlas | |
gdal2tiles.py -p raster -z 0-5 -w none GTA\ V\ Map\ 3.jpg road |
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 template</title> | |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" /> | |
<!--[if lte IE 8]> | |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" /> | |
<![endif]--> | |
<script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script> | |
<script src="leaflet-hash.js"></script> | |
<style type="text/css"> | |
html, body { height: 100% } | |
#map { min-height: 100%; } | |
body { | |
margin: 0; | |
font-family: Helvetica, Arial, sans-serif; font-size: 12px; | |
overflow: hidden; | |
background-color: #f00; | |
} | |
</style> | |
</head><body> | |
<div id="map"></div> | |
<script type="text/javascript"> | |
var atlas = L.tileLayer('atlas/{z}/{x}/{y}.png', { | |
attribution: '<a href="http://www.rockstargames.com/V/">Grand Theft Auto V</a>, web version quickly done by <a href="http://www.somebits.com/weblog/">Nelson Minar</a>', | |
minZoom: 1, maxZoom: 5, noWrap: true, tms: true | |
}); | |
var satellite = L.tileLayer('satellite/{z}/{x}/{y}.png', { | |
attribution: '<a href="http://www.rockstargames.com/V/">Grand Theft Auto V</a>, web version quickly done by <a href="http://www.somebits.com/weblog/">Nelson Minar</a>', | |
minZoom: 1, maxZoom: 5, noWrap: true, tms: true | |
}); | |
var road = L.tileLayer('road/{z}/{x}/{y}.png', { | |
attribution: '<a href="http://www.rockstargames.com/V/">Grand Theft Auto V</a>, web version quickly done by <a href="http://www.somebits.com/weblog/">Nelson Minar</a>', | |
minZoom: 1, maxZoom: 5, noWrap: true, tms: true | |
}); | |
var map = L.map('map', {layers: satellite}); | |
var hash = new L.Hash(map); | |
map.setView([0, 0], 2); | |
L.control.layers({"Satellite": satellite, "Atlas": atlas, "Road": road}, {}).addTo(map); | |
satellite.bringToFront(); | |
</script> | |
</body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment