Search code examples
javascriptleafletgeospatialturfjs

Display length of geo files with Leaflet


I'm trying to build a webpage where I could put files (gpx, kml, geojson...), and Leaflet would display the routes on the map, each of them having a popup with their name and their length in km. I managed to do it all, except for the length... My problem is that turf or cheap-ruler only accept geometries in order to calculate a length, and I can't manage to extract the geometry of my files to give it to turf.

Here is my code:

const fileSelector = document.getElementById('file-selector');
  fileSelector.addEventListener('change', (event) => {
    const fileList = event.target.files;
    console.log(fileList);
    for (file of fileList) {
        fileName = file.name
        extension = fileName.split('.').pop()
        var ObjectURL = URL.createObjectURL(file)
        var line = turf.lineString(ObjectURL)
        var length = turf.length(line, {units: 'meters'})
        var customLayer = L.geoJson(null, {
            onEachFeature(feature, layer)
            {layer.bindPopup('<p><b>' + fileName.replace(/\.[^/.]+$/, "") + '</b></p><p>' + length + '</p>')}
        })
        if (extension == 'kml') {
            omnivore.kml(ObjectURL, null, customLayer).addTo(mymap)}
        else if (extension == 'gpx') {
            omnivore.gpx(ObjectURL, null, customLayer).addTo(mymap)}
        else if (extension == 'csv') {
            omnivore.csv(ObjectURL, null, customLayer).addTo(mymap)}
        else if (extension == 'wkt') {
            omnivore.wkt(ObjectURL, null, customLayer).addTo(mymap)}
        else if (extension == 'geojson') {
            omnivore.geojson(ObjectURL, null, customLayer).addTo(mymap)}
    }});

Here the problem is that ObjectURL is not a geojson object, so I tried another way, by putting the result of omnivore.gpx in a variable :

if (extension == 'gpx') {
        layer_gpx = omnivore.gpx(ObjectURL).addTo(mymap)}
        var line = turf.getCoord(layer_gpx)
        var length = turf.length(layer_gpx, {units: 'meters'})
        L.geoJson(layer_gpx, {
            onEachFeature(feature, layer)
            {layer.bindPopup('<p><b>' + fileName.replace(/\.[^/.]+$/, "") + '</b></p><p>' + length + '</p>')
        }})

It still gives the error "No valid coordinates". Thanks!

Edit : I found by myself!

var customLayer = L.geoJson(null, {
            onEachFeature(feature, layer)
            {layer.bindPopup('<p><b>' + feature.properties.name + '</b></p><p>'+ turf.length(feature.geometry, {units: 'kilometers'}) + ' km</p>')}
        })

Solution

  • I found by myself, and here is the complete code I used:

    const fileSelector = document.getElementById('file-selector');
      fileSelector.addEventListener('change', (event) => {
        const fileList = event.target.files;
        console.log(fileList);
    
        for (file of fileList) {
            fileName = file.name
            extension = fileName.split('.').pop()
    
            var ObjectURL = URL.createObjectURL(file)       
    
            var customLayer = L.geoJson(null, {
                onEachFeature(feature, layer)
                {layer.bindPopup('<p><b>' + feature.properties.name + '</b></p><p>'+ turf.length(feature.geometry, {units: 'kilometers'}) + ' km</p>')}
            })      
    
            if (extension == 'kml') {
                omnivore.kml(ObjectURL, null, customLayer).addTo(mymap)}
    
            else if (extension == 'gpx') {
                omnivore.gpx(ObjectURL, null, customLayer).addTo(mymap)}
    
            else if (extension == 'geojson') {
                omnivore.geojson(ObjectURL, null, customLayer).addTo(mymap)}
    
        }});
    

    I abandoned csv and wkt formats because they don't comply to feature.geometry request, and I didn't really needed them.