Search code examples
node.jsgeojsonopenlayers-3

Saving layer from OpenLayer 3 Map created by user


I'm trying to correctly save an OpenLayer 3 Map layer created by a user in order to display it another map using geoJSON, but I'm having troubles with this.

On the client side I save the dinamic layer in this function:

function addInteractions() {                
    draw = new ol.interaction.Draw({
      source: source,
      type: typeSelect.value
    });
    draw.on("drawend", function(e) {
      var f = e.feature;
      features.push(f);
      geoJson = format.writeFeatures(features);
      console.log(geoJson);
      document.getElementById('js-textarea').value = geoJson;
    });
    map.addInteraction(draw);
    snap = new ol.interaction.Snap({source: source});
    map.addInteraction(snap);
}

Then the geoJSON object is saved into a .json file, but when I try to display it, it doesn't appear on the map.

Here his my display function:

var geoDataUrl = '/data/' + '{{percorso._id}}' + '.json';
var vectorLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
      url: geoDataUrl,
      format: new ol.format.GeoJSON()
    }),
    style: new ol.style.Style({
      fill: new ol.style.Fill({
        color: 'rgba(255, 255, 255, 0.2)'
      }),
      stroke: new ol.style.Stroke({
        color: '#ffcc33',
        width: 2
      }),
      image: new ol.style.Circle({
        radius: 7,
        fill: new ol.style.Fill({
          color: '#ffcc33'
        })
      })
    })
  });       
  var raster = new ol.layer.Tile({
    source: new ol.source.OSM()
  });
  var map = new ol.Map({
    layers: [raster, vectorLayer],
    target: 'map',
    view: new ol.View({
      center: {{#if percorso.mapCenter}}[{{percorso.mapCenter}}] {{else}} ol.proj.transform([9.688053, 45.362760], 'EPSG:4326', 'EPSG:3857'){{/if}},
      zoom: {{#if percorso.zoomLevel}}{{percorso.zoomLevel}} {{else}} 13{{/if}}
    })
  });

I also tested the display function with other layers (for example the provided one on the OpenLayer examples website ) and it works fine

On the server side I save the geoJSONobject with this function, where oggetto_mappa is the dinamic geoJSON object:

var jsonMappa = JSON.stringify(eval("(" + oggetto_mappa + ")"));
require("fs").writeFile("./public/data/" + id_perc + ".json", jsonMappa, 'utf8', function(f_err) {
     if(f_err)
       console.log(f_err);
});

For refernce this is what my function saves onto the .json file:

{
"type":"FeatureCollection",
"features":[
    {
        "type":"Feature",
        "id" : "aa",
        "geometry":
        {
            "type":"LineString",
            "coordinates":[
                [1073328.751180445,5680150.227413875],
                [1077857.6451063417,5682481.556776573],
                [1070385.9255914658,5679156.546046168],
                [1076825.7452244917,5680226.66444216],
                [1073328.751180445,5680169.336670946]
            ]
        },
        "properties":null
    },
    {
        "type":"Feature",
        "id" : "ab",
        "geometry":
        {
            "type":"LineString",
            "coordinates":[
                [1073328.751180445,5680169.336670946],
                [1071628.0273010998,5677130.96479661]
            ]
        },
        "properties":null}
    ]
}

Solution

  • To get things working, replace

    geoJson = format.writeFeatures(features)
    

    with

    geoJson = format.writeFeatures(features, {featureProjection: 'EPSG:3857'})
    

    You may wonder why?

    When you draw in OpenLayers, you are drawing in the projection of the map (the default is EPSG:3857) whereas when you consume a GeoJSON the expected projection is EPSG:4326.

    See the API documentation from ol.format.GeoJSON writeFeatures to understand better

    Some additional informations:

    • when you consume the GeoJSON from your drawing as the coordinates are not in decimal degrees (EPSG:4326) but in meters (EPSG:3857)
    • the order of magnitude for coordinates is different (millions for EPSG:3857 and less than some hundred for EPSG:4326) without accounting for the positive/negative coordinates