Search code examples
openlayersopenlayers-8

In OpenLayers 8.1, manually adding features to a VectorSource from GeoJSON does not render the features


I've created a minimal example to demonstrate the issue. If you set const useGood = true, GeoJSON is rendered as expected, in red fill. If you set const useGood = false, the code fetches the layers and sets them on the source, but they are not visible on the map.

Is there something I'm missing here? I've spent hours attempting to debug this; the sources and layers look identical in both cases.

Minimal reproduction code:

import './style.css';
import { Map, View } from 'ol';
import VectorLayer from 'ol/layer/Vector';
import TileLayer from 'ol/layer/Tile';
import VectorSource from 'ol/source/Vector';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import GeoJSON from 'ol/format/GeoJSON';
import OSM from 'ol/source/OSM';

const useGood = false

const URL = 'sample.json'

const style = new Style({
  fill: new Fill({
    color: [255, 0, 0]
  })
})

const source = new VectorSource({
  format: new GeoJSON({})
})

const badLayer = new VectorLayer({
  visible: true,
  source,
  style: function() {
    return style
  }
})

const goodLayer = new VectorLayer({
  visible: true,
  source,
  style: function() {
    return style
  }
})

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM()
    }),
  ],
  view: new View({
    center: [0, 0],
    zoom: 2
  })
});

if (useGood) {
  map.addLayer(goodLayer)
  source.setUrl(URL)
} else {
  map.addLayer(badLayer)
  const response = await fetch(URL)

  if (response.status !== 200) {
    throw new Error(`failed to fetch ${URL}, status ${response.status} ${response.statusText}`)
  }

  const json = await response.json()

  const format = new GeoJSON({})

  const features = format.readFeatures(json)

  source.addFeatures(features)
}

Solution

  • @Mike was correct. I needed to manually set the projection information, however, I was mistakenly setting the featureProjection to the value of the GeoJSON, not the map's.

    Example fix, with my default map projection:

    const features = format.readFeatures(json, {
      featureProjection: 'EPSG:3857'
    })