[GIS] Read GPX file from desktop in Openlayers 3

gpxopenlayers

I'm aware that Openlayers 3 has the ability to read and parse gpx files using the drag/drop event and I've incorporated this functionality into my map. What I'd also like to do is give the user the ability to 'upload' the file in a more conventional way by browsing through their filesystem.

I've hooked up the basic functionality and the resulting file can be output to a div as text but how do I get the final step of instructing Openlayers to read this information and subsequently display it on a map?

There seems to be very little information regarding this and reading the ol-debug.js file hasn't shed any light. Can anyone give me any pointers please?

Best Answer

create a file selector and then read the file selected. GPX files are text files so there should be any problem with that. Also it is important to know what is the projection of your gpx file as well as the projection of your map. In my example I expect to get gps entries in epsg:4326 and reproject them to EPSG:3857

  1. your html

      <input type="file" id="files" name="files[]" multiple />
      <output id="list"></output>
      <div id="map" class="map"></div>
    
  2. your js

    var gpxFormat = new ol.format.GPX();
    var gpxFeatures;
    function handleFileSelect(evt) {
    var files = evt.target.files; // FileList object
    
    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
    console.log("files[i]",files[i]);
    var reader = new FileReader();
    reader.readAsText(files[i], "UTF-8");
    reader.onload = function (evt) {
       console.log(evt.target.result);
       gpxFeatures = gpxFormat.readFeatures(evt.target.result,{
       dataProjection:'EPSG:4326',
       featureProjection:'EPSG:3857'
       });
       gpxLayer.getSource().addFeatures(gpxFeatures);
       console.log("gpxFeatures",gpxFeatures)
    }
      output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
                  f.size, ' bytes, last modified: ',
                  f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
                  '</li>');
    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
     }
    
    
    var defaultStyle = {
        'Point': new ol.style.Style({
          image: new ol.style.Circle({
            fill: new ol.style.Fill({
              color: 'rgba(255,255,0,0.5)'
            }),
            radius: 5,
            stroke: new ol.style.Stroke({
              color: '#ff0',
              width: 1
            })
          })
        }),
        'LineString': new ol.style.Style({
          stroke: new ol.style.Stroke({
            color: '#f00',
            width: 3
          })
        }),
        'Polygon': new ol.style.Style({
          fill: new ol.style.Fill({
            color: 'rgba(0,255,255,0.5)'
          }),
          stroke: new ol.style.Stroke({
            color: '#0ff',
            width: 1
          })
        }),
        'MultiPoint': new ol.style.Style({
          image: new ol.style.Circle({
            fill: new ol.style.Fill({
              color: 'rgba(255,0,255,0.5)'
            }),
            radius: 5,
            stroke: new ol.style.Stroke({
              color: '#f0f',
              width: 1
            })
          })
        }),
        'MultiLineString': new ol.style.Style({
          stroke: new ol.style.Stroke({
            color: '#0f0',
            width: 3
          })
        }),
        'MultiPolygon': new ol.style.Style({
          fill: new ol.style.Fill({
            color: 'rgba(0,0,255,0.5)'
          }),
          stroke: new ol.style.Stroke({
            color: '#00f',
            width: 1
          })
        })
      };
    
      var styleFunction = function(feature, resolution) {
        var featureStyleFunction = feature.getStyleFunction();
        if (featureStyleFunction) {
          return featureStyleFunction.call(feature, resolution);
        } else {
          return defaultStyle[feature.getGeometry().getType()];
        }
      };
    
    var gpxLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
    
        }),
        style: styleFunction
    });
    var map = new ol.Map({
        target: 'map',
        layers: [
          new ol.layer.Tile({
              source: new ol.source.MapQuest({ layer: 'sat' })
          }),
          gpxLayer
        ],
        view: new ol.View({
            center: ol.proj.fromLonLat([37.41, 8.82]),
            zoom: 4
        })
    });
    
    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    
  3. And a fiddle. I know it is a mess but didnt have the time to tidy it up. You should get the idea.