I have tiles generated by Maperitive from an OSM file, and there's a nice tiles.json
generated with them which specifies neatly the tiles-path, bounding box, minzoom, maxzoom, center, etc. The format is identical to the tileJSON specification given here: https://www.mapbox.com/guides/an-open-platform/#tilejson
But it just blows that the example stopped a step short and inline'd the JSON code into the example's source code, hence rendering it (pun intended) useless. No clue on https://github.com/mapbox/tilejson-spec either. All web searches for this lead to these sites; the rest digress into GeoJSON which is something else entirely. Why in the world would anyone go through the trouble of using JSON if one wasn't importing it from an external file? (no, please don't try to answer that.. it's not the main question. Focus!)
So, a humble request: Please re-write this example code given on mapbox.com, to show an external JSON file being loaded. (And please put in a word with someone there if you know them to post a proper example on the website)
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title></title>
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
.map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var tilejson = {
"tiles": [ "https://api.tiles.mapbox.com/v4/examples.map-i86l3621/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoidHJpc3RlbiIsImEiOiJuZ2E5MG5BIn0.39lpfFC5Nxyqck1qbTNquQ" ],
"minzoom": 0,
"maxzoom": 18
}
L.mapbox.map('map', tilejson, {
scrollWheelZoom: false
}).setView([43.6519,-79.3852], 15);
</script>
</body>
</html>
Edit: Included jquery.min.js
and changed code as advised; am getting a "not well-formed" error in console. I reckon jquery doesn't like tileJSON. This is why full examples ought to be given :P. Please see and advise what needs to change here. Is there a more generic JSON-loader we can use instead of jquery
? I believe we're very close to getting this.
var tilejson;
$.getJSON('pune/tiles.json', function(data) {
tilejson = data;
});
console.log(tilejson.name);
L.mapbox.map('map', tilejson, {
scrollWheelZoom: false
});
Here is the content of tiles.json (loading local tiles, generated by Maperitive
; tested to be valid JSON as per http://codebeautify.org/jsonviewer):
{
"tilejson": "1.0.0",
"name": "Pune 1 to 16",
"description": "Made with Maperitive",
"attribution": "Map data © OpenStreetMap contributors",
"tiles": [
"pune/{z}/{x}/{y}.png"
],
"minzoom": 1,
"maxzoom": 16,
"bounds": [
73.59366818720622,
18.33281593564951,
74.07630689997964,
18.77938751279949
],
"center": [
73.83498754359293,
18.5561017242245,
1
]
}
3 Answers 3
The reason you are getting a "not well formed" error in console is because your tilejson file loads asynchronously, meaning the script continues to execute while the tilejson object is only partly loaded as an incomplete promise object. So when you pass your tilejson object to L.mapbox.map
, you are actually passing a promise object (which it can't parse).
So initialize your map in the success
callback function that $.getJSON() provides. Like so:
$.getJSON('<url to tilejson>', function(tilejson) {
L.mapbox.accessToken = 'pk.eyJ1IjoiamFtZXMtbGFuZS1jb25rbGluZyIsImEiOiJ3RHBOc1BZIn0.edCFqVis7qgHPRgdq0WYsA';
var map = L.mapbox.map('map', tilejson, {
scrollWheelZoom: false
});
});
However, you might still run into problems (e.g. w/ retina screens as outlined in my other answer) because L.mapbox.map
makes some expectations that the tilejson is coming from MapBox's own server. For a more reliable solution, try something like this:
$.getJSON('<url to tilejson>', function(tilejson) {
L.mapbox.accessToken = 'pk.eyJ1IjoiamFtZXMtbGFuZS1jb25rbGluZyIsImEiOiJ3RHBOc1BZIn0.edCFqVis7qgHPRgdq0WYsA';
var map = L.mapbox.map('map', undefined, {
layers: L.tileLayer(tilejson.tiles[0]),
center: tilejson.center.slice(0,2).reverse(),
zoom: tilejson.center[2],
minzoom: tilejson.minzoom,
maxzoom: tilejson.maxzoom,
scrollWheelZoom: false
})
});
-
Thanks James. I'm not fixed on Leaflet of course.. using the Mapbox code to deliver the map is definitely an option. I just found Leaflet easiest to figure out so far. However, the use-case commands : 1. Everything open-source and free; 2.Completely offline. That
accessToken
thing has been scaring me away from Mapbox. Would it be OK to drop that, or deploy with the same token that you have provided without fear?Nikhil VJ– Nikhil VJ2015年01月16日 05:47:24 +00:00Commented Jan 16, 2015 at 5:47 -
@nikhilvj It shouldn't really matter if you use mapbox.js or leaflet.js. leaflet doesn't have an option to pass tilejson to the
L.map
constructor, and while mapbox.js does, as I mentioned mapbox.js makes some (or at least one) assumptions that the tilejson is coming from mapbox servers. So would recommend loading your tilejson and passing the relevant values as options to the map constructor, which should work more-or-less the same for either leaflet'sL.map
or mapbox'sL.mapbox.map
.James Conkling– James Conkling2015年01月16日 15:09:20 +00:00Commented Jan 16, 2015 at 15:09 -
(as for the access token, I don't know if it's needed b/c you are loading tiles from your own service--not mapbox's. experiment w/ including it or not)James Conkling– James Conkling2015年01月16日 15:12:17 +00:00Commented Jan 16, 2015 at 15:12
-
...also, if you are unsure of whether to go w/ mapbox.js or leaflet.js (and I don't think it's a big question, they are both pretty similar/would likely work just as well), compare the documentation for each, particularly the
map
constructor: L.map and L.mapbox.map.James Conkling– James Conkling2015年01月16日 15:15:04 +00:00Commented Jan 16, 2015 at 15:15 -
Is it still working? Please, can you provide a jsfiddle for this? :)pnz1337– pnz13372019年11月29日 10:20:14 +00:00Commented Nov 29, 2019 at 10:20
Last time I tried to pass tileJSON directly to the L.mapbox.map
constructor, I ran into issues when mapbox.js tried to automatically load retina tiles from my non-mapbox tileserver. If you are using a retina device, could point to your problem. If not, might cause additional problems after you've fixed your current issue. Check your console to see if you are getting 404 errors, something like:
GET http://<your tile url>/5/17/[email protected] 404 (Not Found)
mapbox automatically appends @2x
when a request is made from a retina device.
When you load your JSON, if you still run into issues passing it directly to L.mapbox.map
, you can always pass it's individual parts as options, similar to how you would work with leaflet's L.map
. E.g.:
L.mapbox.map('map', undefined, {
layers: L.tileLayer(tileJSON.tiles[0]),
minZoom: tileJSON.minzoom,
maxZoom: tileJSON.maxzoom
});
-
Hi.. no, there ain't no retina device here for miles around. This use case is for off-the-internet schools in third world countries. Think "junked CRTs". It's dead-simple tiles here, loading on open-source browsers like Firefox, over a local LAN. JQuery is simply refusing to even load the JSON at this point. ("not well-formed"). The "when you load your JSON" stage is what needs to be solved first. I'm sure that tiles[0] command will work once that happens. Please give a full example demonstrating the JSON being loaded successfully.Nikhil VJ– Nikhil VJ2015年01月15日 15:12:29 +00:00Commented Jan 15, 2015 at 15:12
-
Please just paste your code from the
Last time I tried to pass tileJSON directly to the L.mapbox.map constructor
>> that's what I'm looking for and just not being able to find around here. Full code! (of course, the JSON better be coming from an external JSON file.. not something inline)Nikhil VJ– Nikhil VJ2015年01月15日 15:19:50 +00:00Commented Jan 15, 2015 at 15:19
I would use getJSON() from the jquery library:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
var tilejson;
$.getJSON('/path/to/your.json', function(data) {
tilejson = data;
});
-
Thanks. What's the jquery .js URL.. have a to include the script up at the top, right?Nikhil VJ– Nikhil VJ2015年01月13日 19:54:26 +00:00Commented Jan 13, 2015 at 19:54
-
Edited answer to provide jquery cdn linkjmcbroom– jmcbroom2015年01月13日 20:08:22 +00:00Commented Jan 13, 2015 at 20:08
-
Blended this in.. I'm getting a "not well formed" error in console. Adding the new code in the question, please see and tell what needs fixing.Nikhil VJ– Nikhil VJ2015年01月14日 07:38:10 +00:00Commented Jan 14, 2015 at 7:38
-
Try jsonlint. It might help point out any issues with your tileJSON.James Conkling– James Conkling2015年01月14日 14:32:18 +00:00Commented Jan 14, 2015 at 14:32
-
1Alternatively, trying loading the tileJSON with jQuery's $.ajax, which is more permissive w/ what can and can't be passed.James Conkling– James Conkling2015年01月14日 14:53:31 +00:00Commented Jan 14, 2015 at 14:53
Explore related questions
See similar questions with these tags.