2

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
    var image = L.imageOverlay('img/background.png', bounds).addTo(map);


    //create map icon class
    var TaladasIcon = L.Icon.extend({
    options: {
        iconSize:     [50, 50],
        iconAnchor:   [25, 25],
        popupAnchor:  [0, -25]
    }
});

    //define icons
    var metropolisIcon = new TaladasIcon({iconUrl: 'img/metropolis.png'}),
        cityIcon = new TaladasIcon({iconUrl: 'img/city.png'}),
        townIcon = new TaladasIcon({iconUrl: 'img/town.png'}),
        villageIcon = new TaladasIcon({iconUrl: 'img/village.png'}),
        innIcon = new TaladasIcon({iconUrl: 'img/tankard.png'});

//- load geoJson file
    L.geoJson(json-test, {
        onEachFeature: layer.setIcon(metropolisIcon)
    }).addTo(map);

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);
var image = L.imageOverlay('img/kisandra.png', bounds).addTo(map);

var TaladasIcon = L.Icon.extend({
  options: {
      iconSize:     [50, 50],
      iconAnchor:   [25, 25],
      popupAnchor:  [0, -25]
  }
});

var metropolisIcon = new TaladasIcon({iconUrl: 'img/metropolis.png'}),
    cityIcon = new TaladasIcon({iconUrl: 'img/city.png'}),
    townIcon = new TaladasIcon({iconUrl: 'img/town.png'}),
    villageIcon = new TaladasIcon({iconUrl: 'img/village.png'}),
    innIcon = new TaladasIcon({iconUrl: 'img/tankard.png'});

var jsonMetropolis = new L.geoJSON();

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

jsonMetropolis.addTo(map);
  • Any errors in the debugger console? It should be L.geoJSON. – TomazicM Apr 23 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 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 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 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 at 18:42
2

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) {
      jsonMetropolis.addData(data);
    });
    jsonMetropolis.addTo(map);
  }
});
| improve this answer | |
  • 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 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 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 at 21:36
0

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
        ]
      }
    }
  ]
}
| improve this answer | |
  • Just tested and unfortunately that wasn't the (sole) problem. – Merion Apr 23 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.