# How to work with GeoJSON, Leaflet and pixel coordinates?

I'm a noob trying to piece together a - as I thought - simple thing: A Leaflet map based on a raster picture with markers coming from a GeoJSON file. As this is a fictional map, I use the `CRS.Simple` in Leaflet and thus just use my picture pixels as coordinate system. From some examples I put together the following:

``````    var map = L.map('map', {
crs: L.CRS.Simple,
minZoom: -1
});

//- set the image width and height to w and h
var w = 1700;
var h = 2200;

//the stuff to be able to work with xy instead of latlon
var yx = L.latLng;
var xy = function(x, y) {
if (L.Util.isArray(x)) {    // When doing xy([x, y]);
return yx(x[1], x[0]);
}
return yx(y, x);  // When doing xy(x, y);
};

var bounds = [xy(0, 0), xy(w, h)];

//this makes the map fit the bounds we just defined
map.fitBounds(bounds).setMaxBounds(bounds);

// insert image name here

//create map icon class
options: {
iconSize:     [50, 50],
iconAnchor:   [25, 25],
popupAnchor:  [0, -25]
}
});

//define icons
var metropolisIcon = new TaladasIcon({iconUrl: 'img/metropolis.png'}),

L.geoJson(json-test, {
onEachFeature: layer.setIcon(metropolisIcon)
``````

My GeoJSON file looks like this so far:

``````{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Cityname",
"description": "This is a very important city",
},
"geometry": {
"type": "Point",
"coordinates": [
719,
1210
]
},
},
]
}
``````

There is obviously something wrong, as I only see the background image but no markers from the GeoJSON. I think it might have to do with part that exchanges latlng for xy, but honestly I'm not sure what exactly happens there. It does work if I define a marker directly in the script, but not from the GeojJSON. Which is a bummer because I plan on having quite a few markers and being able to write them down in a table on geojson.io would save me a lot of time.

Can anyone point out what I'm doing wrong here?

EDIT: Second try with AJAX, still not working:

``````var map = L.map('map', {
crs: L.CRS.Simple,
minZoom: -1
});

var w = 1700;
var h = 2200;

var yx = L.latLng;
var xy = function(x, y) {
if (L.Util.isArray(x)) {    // When doing xy([x, y]);
return yx(x[1], x[0]);
}
return yx(y, x);  // When doing xy(x, y);
};

var bounds = [xy(0, 0), xy(w, h)];
map.fitBounds(bounds).setMaxBounds(bounds);

options: {
iconSize:     [50, 50],
iconAnchor:   [25, 25],
popupAnchor:  [0, -25]
}
});

var metropolisIcon = new TaladasIcon({iconUrl: 'img/metropolis.png'}),

var jsonMetropolis = new L.geoJSON();

\$.ajax({
dataType: "json",
url: "json-test.geojson",
success: function(data) {
\$(data.features).each(function(key, data) {
});
}
});

``````
• Any errors in the debugger console? It should be `L.geoJSON`. – TomazicM Apr 23 '20 at 16:58
• good catch! I corrected the wrong cases, but the console still shows two problems: 1. syntax error on the "type" : "Feature Collection", line - the : is wrong appearantly? and 2. json is not define, which might be related – Merion Apr 23 '20 at 17:50
• What is missing from your code above is definition of `json-test`. What is this and where does it come from? – TomazicM Apr 23 '20 at 17:58
• my html file's body looks like this <div id='map'></div> <script src="js/jquery-3.5.0.min.js" ></script> <script src="js/leaflet.js" ></script> <script src="js/json-test.geojson" ></script> <script src="js/kisandra.js"></script> where kisandra.js is what you see above. I thought putting it this way makes the html load the geoJSON first and the main script can then use it. Mistake? – Merion Apr 23 '20 at 18:10
• If `json-test.geojson` file contains just your raw GeoJSON data, not definition of JS object in the form of `var json-test = {"type": "FeatureCollection", ...`, then it cannot work. In this case you have to first read in the GeoJSON data with AJAX (see for example leaflet-ajax plugin github.com/calvinmetcalf/leaflet-ajax). See also gis.stackexchange.com/questions/68489/… – TomazicM Apr 23 '20 at 18:42

Answer will be based on second try with AJAX (I added the code, gotten via Google drive).

There are a few things wrong in the code:

• `L.geoJSON()` is not object, but function creating an instance of object, so the correct syntax for creating GeoJSON layer is `var jsonMetropolis = L.geoJSON(...`
• When reading GeoJSON file `json-test.geojson` with AJAX, it must contain pure GeoJSON, not JS assignment in the form of `var json-test = { ...`
• Since GeoJSON data is read async, GeoJSON layer has to be added to the map when reading data is finished, inside AJAX success callback.

You can also use `pointToLayer` option to assign custom icons to GeoJSON points.

So to wrap it up, the relevant part of the code could then look something like this (tested):

``````var jsonMetropolis = L.geoJSON([], {
pointToLayer: function (feature, yx) {
return L.marker(yx, {
icon: metropolisIcon
});
}
});

\$.ajax({
dataType: "json",
url: "json-test.geojson",
success: function(data) {
\$(data.features).each(function(key, data) {
});
}
});
``````
• Thank you for all your patience and work! I'm still very new to javascript and turns out it's harder than I thought. I corrected the geojson and pasted your code over what I got as import function. Unfortunately it still does not work. You can see it (or not) here: maps.dungeonmasterresources.com/test/Kisandra_map.html Must be still doing something wrong. – Merion Apr 24 '20 at 20:23
• If you look in the browser network debugger, you'll see that browser cannot find `json-test.geojson` file on server. Either file is not there or MIME type `.geojson` is not enabled on server. – TomazicM Apr 24 '20 at 20:51
• hmm... file is there: maps.dungeonmasterresources.com/test/js/json-test.geojson same directory as the js file that's calling it. Something must be wrong with just naming the file name. If I use " url: "maps.dungeonmasterresources.com/test/js/json-test.geojson" " it works! This one I will hopefully solve on my own. Thank you so much! – Merion Apr 24 '20 at 21:36

If it works when the features are defined directly in the script, it means the problem might come from the GeoJSON file. A validation with geojsonlint suggests to try removing the 3 trailing commas:

``````{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Cityname",
"description": "This is a very important city"
},
"geometry": {
"type": "Point",
"coordinates": [
719,
1210
]
}
}
]
}
``````
• Just tested and unfortunately that wasn't the (sole) problem. – Merion Apr 23 '20 at 16:17