最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Leaflet: How to fetch geojson from URL and pass it to L.geoJson - Stack Overflow

programmeradmin2浏览0评论

I try to load a geojson from an URL and display it in a map with leaflet:

<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="/[email protected]/dist/leaflet.css"/>
    <script src="/[email protected]/dist/leaflet.js"></script>
</head>

<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
    let url = '.geojson';
    let shape_obj = await (await fetch(url)).json();
    return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);
</script>
</body>
</html>

I get on the JS Console:

Uncaught Error: Invalid GeoJSON object.
    at De (GeoJSON.js:221)
    at i.addData (GeoJSON.js:117)
    at initialize (GeoJSON.js:92)
    at new i (Class.js:22)
    at Object.Ke (GeoJSON.js:439)
    at leaflet.html:21

If possible, I would like to not use jQuery. Thanks for any input!

EDIT: I replaced the url with an actual GeoJSON file, thanks @IvanSanchez!

I try to load a geojson from an URL and display it in a map with leaflet:

<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="https://unpkg./[email protected]/dist/leaflet.css"/>
    <script src="https://unpkg./[email protected]/dist/leaflet.js"></script>
</head>

<body>
<div id="my_map" style="height: 600px"></div>
<script>
const map = L.map('my_map')
L.tileLayer('https://{s}.tile.openstreetmap/{z}/{x}/{y}.png').addTo(map);
map.setView([37.8, -96], 4);
async function load_shapefile() {
    let url = 'https://raw.githubusercontent./shawnbot/topogram/master/data/us-states.geojson';
    let shape_obj = await (await fetch(url)).json();
    return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);
</script>
</body>
</html>

I get on the JS Console:

Uncaught Error: Invalid GeoJSON object.
    at De (GeoJSON.js:221)
    at i.addData (GeoJSON.js:117)
    at initialize (GeoJSON.js:92)
    at new i (Class.js:22)
    at Object.Ke (GeoJSON.js:439)
    at leaflet.html:21

If possible, I would like to not use jQuery. Thanks for any input!

EDIT: I replaced the url with an actual GeoJSON file, thanks @IvanSanchez!

Share Improve this question edited Feb 25, 2021 at 10:07 Kilian Röhner asked Feb 24, 2021 at 16:50 Kilian RöhnerKilian Röhner 3852 silver badges10 bronze badges 2
  • 1 This is an XY problem. The JSON is not GeoJSON (and is not a shapefile as well), but it looks like it's TopoJSON instead. – IvanSanchez Commented Feb 24, 2021 at 16:55
  • Thank you @IvanSanchez! I replaced the url with a proper GeoJSON. Unfortunately, the problem persists. – Kilian Röhner Commented Feb 25, 2021 at 10:08
Add a ment  | 

2 Answers 2

Reset to default 5

If you want to extract the geojson and use it later you need to create another function to await the result as the operation is asynchornous:

<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="https://unpkg./[email protected]/dist/leaflet.css" />
  <script src="https://unpkg./[email protected]/dist/leaflet.js"></script>
</head>

<body>
  <div id="my_map" style="height: 600px"></div>
  <script>
    const map = L.map('my_map')
    L.tileLayer('https://{s}.tile.openstreetmap/{z}/{x}/{y}.png').addTo(map);
    map.setView([37.8, -96], 4);

    async function load_shapefile() {
      let url = 'https://raw.githubusercontent./shawnbot/topogram/master/data/us-states.geojson';
      const response = await fetch(url)
      const shape_obj = await response.json();
      console.log(shape_obj);
      return shape_obj;
    }

    async function main() {
      const json = await load_shapefile();
      L.geoJson(json).addTo(map);
    }

    main();
  </script>
</body>

</html>

Otherwise if you do not want to use the geojson instance further use then to fetch the data and immediately use them.

<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="https://unpkg./[email protected]/dist/leaflet.css" />
  <script src="https://unpkg./[email protected]/dist/leaflet.js"></script>
</head>

<body>
  <div id="my_map" style="height: 600px"></div>
  <script>
    const map = L.map('my_map')
    L.tileLayer('https://{s}.tile.openstreetmap/{z}/{x}/{y}.png').addTo(map);
    map.setView([37.8, -96], 4);

    let url = 'https://raw.githubusercontent./shawnbot/topogram/master/data/us-states.geojson';
    const response = fetch(url).then(response => response.json()).then(response => {
      L.geoJson(response).addTo(map);
    })
  </script>
</body>

</html>

@kboul's answer already points out how to fix it, but doesn't explain why it fails in the first place.

The original code is failing because async functions return an instance of Promise, and the L.GeoJSON constructor expects a static data structure.

So instead of

async function load_shapefile() {
    let url = 'https://raw.githubusercontent./shawnbot/topogram/master/data/us-states.geojson';
    let shape_obj = await (await fetch(url)).json();
    return shape_obj
}
L.geoJson(load_shapefile()).addTo(map);

You can do

load_shapefile().then(function(geojsonData){
    L.geoJson(load_shapefile()).addTo(map);
});

And abusing the syntax of .then() a bit to pass function references only:

load_shapefile().then(L.geoJson).then(map.addLayer.bind(map));

<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="https://unpkg./[email protected]/dist/leaflet.css" />
  <script src="https://unpkg./[email protected]/dist/leaflet.js"></script>
</head>

<body>
  <div id="my_map" style="height: 600px"></div>
  <script>
    const map = L.map('my_map')
    L.tileLayer('https://{s}.tile.openstreetmap/{z}/{x}/{y}.png').addTo(map);
    map.setView([37.8, -96], 4);

    async function load_shapefile() {
      let url = 'https://raw.githubusercontent./shawnbot/topogram/master/data/us-states.geojson';
      const response = await fetch(url)
      const shape_obj = await response.json();
      console.log(shape_obj);
      return shape_obj;
    }

    load_shapefile().then(L.geoJson).then(map.addLayer.bind(map));
    
  </script>
</body>

</html>

发布评论

评论列表(0)

  1. 暂无评论