Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 271
Miles Avatar asked May 28 '15 15:05

Miles


1 Answers

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/

like image 172
tsauerwein Avatar answered Nov 03 '22 15:11

tsauerwein