1

I am currently trying to make a simple visualization using Mapbox that is based on additional data provided by a local geojson file. I cannot upload this file to Mapbox and would like to keep it local.

I have used this base code from Mapbox that I have modified to include a local geojson file that is structured like this:

{"features": [{"geometry": null, "location": {"coordinates": [40.730610, -73.935242], "type": "Point"}, "properties": {"X": "1", "group": "1"}, "type": "Feature"},...}

I have modified the example code from Mapbox so that it is now:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Style circles with a data-driven property</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.js'></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.48.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibG9ubmliZXNhbmNvbiIsImEiOiJjamxjaWNpOHQwMHV0M3FwaHhneGhvY2l2In0.7GxI8W_dnTKITNF4hEvZeQ';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v9',
    zoom: 12,
    center: [-73.935242, 40.730610],
    pitch: 20,
});


var url = "GeoObs.json.json"

map.on('load', function () {

    var layers = map.getStyle().layers;

    var labelLayerId;
    for (var i = 0; i < layers.length; i++) {
        if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
            labelLayerId = layers[i].id;
            break;
        }
    }

     map.addSource("my_data", {
        type: "geojson",
        data: url //"./GeoObs.json",
        /*cluster: true,
        clusterMaxZoom: 15, // Max zoom to cluster points on
        clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)*/
    });


    map.addLayer({
        'id': 'population',
        'type': 'circle',
        source: 'my_data',
        'source-layer': 'my_data',
        'paint': {
            // make circles larger as the user zooms from z12 to z22
            'circle-radius': {
                'base': 1.75,
                'stops': [[12, 2], [22, 180]]
            },
            // color circles by ethnicity, using a match expression
            // https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match
            'circle-color': [
                'match',
                ['get', 'group'],
                '1', '#fbb03b',
                '2', '#223b53',
                '3', '#e55e5e',
                '4', '#3bb2d0',
                /* other */ '#ccc'
            ]
        }
    });

    map.addLayer({
        'id': '3d-buildings',
        'source': 'composite',
        'source-layer': 'building',
        'filter': ['==', 'extrude', 'true'],
        'type': 'fill-extrusion',
        'minzoom': 15,
        'paint': {
            'fill-extrusion-color': '#aaa',

            // use an 'interpolate' expression to add a smooth transition effect to the
            // buildings as the user zooms in
            'fill-extrusion-height': [
                "interpolate", ["linear"], ["zoom"],
                15, 0,
                15.05, ["get", "height"]
            ],
            'fill-extrusion-base': [
                "interpolate", ["linear"], ["zoom"],
                10, 0,
                15.05, ["get", "min_height"]
            ],
            'fill-extrusion-opacity': .6
        }
    }, labelLayerId);
});

</script>

</body>
</html>

I get the following error:

Error: Source layer "my_data" does not exist on source "my_data" as specified by style layer "population"
    at i._validateLayer (style.js:274)
    at i.addLayer (style.js:576)
    at o.addLayer (map.js:1175)
    at o.<anonymous> (index3.html:52)
    at o.L.fire (evented.js:115)
    at o._render (map.js:1619)
    at map.js:1683

Can anyone point me in the direction of a possible mistake here and hopefully how to fix it. You can use the example geojson I gave you to try out this example. Just copy paste it into a file called: GeoObs.json if you want the code to right away give the same error.

LBes
  • 3,366
  • 1
  • 32
  • 66

3 Answers3

3

For the population layer, comment out the line, because you do not have such a layer:

'source-layer': 'my_data',

And maybe you have an extra ".json" in the URL:

GeoObs.json.json

[ https://jsfiddle.net/c5nauwgx/ ]

stdob--
  • 28,222
  • 5
  • 58
  • 73
  • Thanks for posting this out. So what do you use the source-layer for then? I also have a hard time understanding what labelLayerId is used for and why we had it at the end of the 3D building new layer. I guess that @eczajk also rightfully pointed that my geojson was wrong which is why even with you solution I don't see any point =) – LBes Sep 12 '18 at 20:38
  • I couldn't accept both answer sorry. Previous answer also pointed out the problem with my geojson, so I accepted this. But I upvoted you anyway – LBes Sep 12 '18 at 22:13
  • @LBes source-layer is for referring to specific layers when Mapbox Vector Tiles are used as the source. `labelLayerId` is used to indicate where the new layer will be placed (i.e. the new building layer gets placed *before* the layer that relates to the provided id). – eczajk Sep 12 '18 at 22:17
3

As the error states, your GeoJSON source does not have a source layer. So you can remove the 'source-layer' property from the map.addLayer call.

Your GeoJSON also needs to be modified to a proper FeatureCollection:

{
  "type": "FeatureCollection",
  "features": [
    {
      "geometry": {
        "type": "Point",
        "coordinates": [
          -73.935242,
          40.730610
        ]
      },
      "properties": {
        "X": "1",
        "group": "1"
      },
      "type": "Feature"
    }
  ]
}
eczajk
  • 447
  • 4
  • 15
  • Thanks will try that right away. BTW, do you know if there is any way to actually use csv instead of geojson? Or any other data format that might be better somehow for my purposes? – LBes Sep 12 '18 at 20:27
  • @LBes I don't believe there is any native way of using CSV directly. You might look into the @turf/helpers module which has handy tools for creating GeoJSON (see point and featureCollection). – eczajk Sep 12 '18 at 22:04
  • ok thanks. Cause I'm trying to figure out what is wrong with my python csv to geojson converter based on this stackoverflow answer: https://stackoverflow.com/questions/48586647/python-script-to-convert-csv-to-geojson but I can't seem to figure it out :). Thanks anyways for the reply :). I'll mark as accepted :) – LBes Sep 12 '18 at 22:12
0

This example from MapLibre helped me and also works with Mapbox GL JS. It adds a little interactivity to your map by giving you the option to select a local geojson file within the map.

https://maplibre.org/maplibre-gl-js-docs/example/local-geojson/

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/32123227) – ethry Jul 02 '22 at 21:18