How do I dynamically load GeoJSON data, based on the map extent, into my OpenLayers 3.5.0 map layer?
Asked Answered
A

1

5

I am migrating from OpenLayers 3.2.0 to 3.5.0 and am having trouble loading my GeoJSON data into my vector layer. I have it working, but I'm transforming the geometry of the features from my GeoJSON data source before I add them to my vector source.

Is there a way to make OpenLayers 3.5.0 apply the transformation automatically?

The data from my GeoJSON data source uses the EPSG:4326, I believe that I need to re-project the geometries to EPSG:3857 in order to display them on my map. The GeoJSON data source has the projection information in it's crs attribute and my vector source also has it's projection set. Still, the feature geometries are not transformed on their own.

I need to pass the bounds of the viewable map area via the URL to my GeoJSON data source, I do not want to load all of the data at once. I have a loader function on my vector source that gets the current map extent and builds the URL for the request.

Sample Data from my GeoJSON source is available, it validates through a linter and I believe it to be reasonable.

Below is the current code that I am using.

var vectorFormat = new ol.format.GeoJSON();
var featureStyle = new ol.style.Style({
    image: new ol.style.Circle({
      radius: 5,
    fill: new ol.style.Fill(
      {color: 'rgba(255, 69, 0, 0.75)'}),
    stroke: new ol.style.Stroke(
      {color: 'rgba(255, 0, 0, 0.95)', width: 1})
    })
 });

var vectorSource = new ol.source.Vector({
    projection: new ol.proj.Projection({'code':'EPSG:3857'}),
    strategy: ol.loadingstrategy.bbox,
    loader: function(extent, resolution, projection) {
      var coordinate1 = ol.proj.transform([extent[0], extent[1]],
        'ESPG:3857', 'EPSG:4326')
      var coordinate2 = ol.proj.transform([extent[2], extent[3]],
        'ESPG:3857', 'EPSG:4326')
      var url = 'api/sites/geo/bounds/4326/' + coordinate1[1] 
        + ',' + coordinate1[0] + '/' + coordinate2[1] + ',' 
        + coordinate2[0] + "/";
        $.ajax({
            url: url,
            dataType: 'json'
        }).then(function(response) {
            var features = vectorFormat.readFeatures(response);
            var transformFn = ol.proj.getTransform(
              response.crs.properties.name, projection);
            for(index in features) {
                var feature = features[index];
                feature.getGeometry().applyTransform(transformFn);
            }
            vectorSource.addFeatures(features);
        });
    }
});

this.state.map = new ol.Map({
    target: 'map',
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      new ol.layer.Vector({
        source: vectorSource,
          style: featureStyle
        })
     ],
     view: new ol.View({
        center: this.transformToOl(this.state.center),
        zoom: this.state.zoom
      })
});

Any help or pointers in the right direction would be greatly appreciated. :-D

Annelid answered 28/5, 2015 at 15:2 Comment(3)
@tsauerwein clarified the issue for me, the question here is how should I write my loader function so that the features are transformed? In the example above I manually transform them, is that the only way? I need my own loader function so that I can alter the URL to include the map extent.Annelid
I think @tsauerwein meant you don't need transform anything. Just read/include the features of your geojson.Affidavit
If I can provide the source with an URL that doesn't need any additional parameters, then @tsauerwein is correct: the data loads and is automatically transformed. All of the OpenLayers examples that have parameters in the URL, however, have a "loader" function and that appears to leave the coordinates un-transformed. For instance, this answer: #26844912Annelid
E
8

Yes, OpenLayers can do the reprojection for you. You don't even have to set the projection on the source. The geometries will be automatically reprojected to the view projection.

var vectorSource = new ol.source.Vector({
  url: 'file.json',
  format: new ol.format.GeoJSON()
});

http://jsfiddle.net/h9zwjf88/

Update

In case you want to you use a custom loader, you can specify the target projection when parsing the features (see also ol.format.GeoJSON.html#readFeatures):

var vectorSource = new ol.source.Vector({
  strategy: ol.loadingstrategy.bbox,
  loader: function(extent, resolution, projection) {
    $.ajax(url).then(function(response) {
      var features = format.readFeatures(response,
        {featureProjection: 'EPSG:3857'});
      vectorSource.addFeatures(features);
    });
  }
});

http://jsfiddle.net/h9zwjf88/1/

Evasive answered 28/5, 2015 at 15:33 Comment(3)
I believe my problem lies within my custom data loader for my vector source. The REST service providing the GeoJSON data is pretty big, so I'm passing the bounds for the data I'd like back in the URL. In order to do that, it looks like I also have to handle receiving that data, so I have the then function on the loader. It could be that if I want to be able to alter the URL like this, then I have to do the transformation myself.Annelid
@Annelid I updated my answer with a custom loader example.Evasive
Thank you! I had tried passing a projection value in the readFeatures function but not featureProjection. That is just what I needed to get this working.Annelid

© 2022 - 2024 — McMap. All rights reserved.