public
Last active

GTA V Map Viewer

  • Download Gist
README.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14
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
leaflet-hash.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
(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);
maketiles.sh
Shell
1 2 3 4 5
#!/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
map.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
<!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>

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.