2

I am working on an openlayers map to add a vector layer with source from local geojson file in a create-react-app project, but the vector layer cannot be shown.

Here is my code:

import React,{ Component } from 'react'
import './BaseMap.scss'
import 'ol/ol.css'
import {Map, View} from 'ol'
import TileLayer from 'ol/layer/Tile'
import {fromLonLat} from 'ol/proj'
import XYZ from 'ol/source/XYZ'
import {defaults, ScaleLine } from 'ol/control'
import GeoJSON from 'ol/format/GeoJSON';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';

const vectorLayer = new VectorLayer({
    source: new VectorSource({
        url: './shanghang_lj.json',
        format: new GeoJSON()
    }),
    style: function(feature) {
        style.getText().setText(feature.get('name'));
        return style;
    }
 });


const tian_di_tu_road_layer = new TileLayer({
    title: "road_layer",
    source: new XYZ({
        url: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}"
    })
});
const tian_di_tu_annotation = new TileLayer({
    title: "annotation",
    source: new XYZ({
        url: 'http://t4.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}'
    })
});


export class BaseMap extends Component{
    constructor(props){
        super(props);

    };


    componentDidMount(){
        let map = new Map({
            controls: new defaults({
                attributionOptions: {
                    collapsible: false
                }
              }).extend([
                new ScaleLine()
              ]),
            target:'basemap',
            layers:[
                tian_di_tu_road_layer,//can be displayed
                tian_di_tu_annotation,//can be displayed
                vectorLayer//can not be displayed
            ],
            view:new View({
                center:fromLonLat([116.4,25.0]),
                zoom:10
            })
        })

    }


    render(){
        return(
           <div id="basemap" className='basemap'></div>    
        )
    }
}

And I got the error from console:

Uncaught SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at getObject (JSONFeature.js:188)
at GeoJSON.readFeatures (JSONFeature.js:56)
at VectorSource.<anonymous> (featureloader.js:87)

Then I tried another way to pass geojson data:

import border_shanghang from './shanghang_lj.json';

const vectorLayer = new VectorLayer({
    source: new VectorSource({
        features: (new GeoJSON()).readFeatures(border_shanghang)
    }),
});

No error appears in the console, but still no vector layer displayed.

I've been struggled with this problem for long. Any help will be appreciated.

BTW, the code works if I run it without react.

Emma Huang
  • 23
  • 4

1 Answers1

0

I tried implementing this with a sample geojson file and what worked for me was:

import border_shanghang from './shanghang_lj.geojson'; // I got a sample geojson from the web
const style = // ...;
const vectorLayer = new VectorLayer({
  source: new VectorSource({
    url: border_shanghang,
    format: new GeoJSON()
  }),
  style: function (feature) {
    style.getText().setText(feature.get('name'));
    return style;
  }
});
// ...

everything else the same. The only difference was to put the import straight into the url field of the VectorSource, and rename your file from a .json to .geojson

izb
  • 562
  • 4
  • 11
  • But there is still one thing confusing me. Why the url of file path './shanghang.lj_json' and the `.json` file instead of `.geojson` file works when running the code without React? – Emma Huang Sep 07 '18 at 07:29
  • I believe its due to the way webpack imports files. There is a special import protocol for `.json` files that turns them into a JS object when imported. If you put `console.log(border_shanghang)` in your constructor and run the app with it as a `.geojson` it will print the file path; if you change it to `.json`, it will print an Object (`{ features: Array(X), type: "FeatureCollection" }`), etc. You can fix this by digging into your webpack config which requires [ejecting your app](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject) – izb Sep 07 '18 at 15:13
  • I see. But if a `.json` file is turned into a JS object, why the vector data wasn't displayed when I imported `.json` file and tried this way to create the vector layer: `const vectorLayer = new VectorLayer({ source: new VectorSource({ features: (new GeoJSON()).readFeatures(border_shanghang) }), });` – Emma Huang Sep 08 '18 at 07:18
  • After doing some digging i came across [this](https://stackoverflow.com/questions/32455040/how-to-specify-the-projection-for-geojson-in-openlayers3) link talking about a similar problem. It looks like there are some additional options you must specify when parsing a JS Object. I got this to work: `const source = new VectorSource({ features: (new GeoJSON()).readFeatures(border_shanghang, { featureProjection: 'EPSG:3857' }), });` and the rest the same – izb Sep 08 '18 at 18:31
  • It seems that parsing straight from the url is much easier! If you do want to be able to parse json files by uncluding the url like `url: '/shanghang_lj.json'`, you have to move your `.json` file into the `/public` folder that `create-react-app` builds for you. – izb Sep 08 '18 at 18:39
  • 1
    Thank you very much for your time! It's much clear now! – Emma Huang Sep 11 '18 at 02:20