makinacorpus / Leaflet.FileLayer

Loads files locally (GeoJSON, KML, GPX) as layers using HTML5 File API
http://makinacorpus.github.io/Leaflet.FileLayer/
MIT License
273 stars 91 forks source link

Editing loaded shapes with leaflet draw controls #22

Closed natoelgato closed 7 years ago

natoelgato commented 8 years ago

Hi, great piece of code, thanks!

When I load up a KML, I can view them on the map no problem. However the shapes are not editable with the leaflet draw controls.

Any idea how I can get this to work?

Thanks again.

leplatrem commented 8 years ago

It is hard to help you from here. You could probably try to setup a JSFiddle (or similar) to reproduce your problem in a minimalist fashion.

What makes you think the problem comes from leaflet.filelayer and not leaflet.draw by the way ? :)

rukayaj commented 8 years ago

It is an awesome piece of code.

natoelgato are you using django-leaflet and using a CreateView or something? From what I understand, django-leaflet instantiates its own new L.Control.Draw() which it populates with a featureGroup called drawnItems. You need to make sure that you add your polygon or whatever from your fileLayer to THAT particular featureGroup. The way I did it was:

$(window).on('map:init', function(e) {
    // Get the map
    map = e.originalEvent.detail.map;

    // Get the featureGroup that is used by django-leaflet's drawControl 
    var featureGroup;
    map.on('map:loadfield', function (e) {
        featureGroup = e.field.drawnItems;
    });

    // Add the fileLayer
    control = L.Control.fileLayerLoad({          
        // Add to map after loading (default: true) ?
        addToMap: false,
        .... All other options
    });
    control.addTo(map);

    // When the data is loaded
    control.loader.on('data:loaded', function (e) {
        // Get the geojson layer
        gLayer = e.layer.getLayers()[0];

        // If it's a KML it will have altitude, so iterate through and strip them out
        newLatLngs = []
        oldLatLngs = gLayer.getLatLngs();
        $(oldLatLngs).each(function(index, obj) {
            newLatLng = {lat: obj.lat, lng: obj.lng} // Can also: new L.LatLng(obj.lat, obj.lng);
            newLatLngs.push(newLatLng);
        })

        // Set the new latlngs for the polygon
        gLayer.setLatLngs(newLatLngs);

        // Add the gLayer to the featureGroup
        featureGroup.addLayer(gLayer);
    });
});

But now I am stuck because when I submit it thinks the geometry field is null :( although once I use the draw buttons on the map to physical edit the polygon and then submit it, it works. Leplatrem am I approaching this the right way?

rukayaj commented 8 years ago

Ok, so I worked out how to do it. I hope this helps you natoelgato:


$(document).ready(function() {
    // This function is called when the map initializes (automatically via django-leaflet)
    $(window).on('map:init', function(e) {
        // Get a reference to the map
        map = e.originalEvent.detail.map;

        // Store the featureGroup (drawnItems) which django-leaflet's drawControl uses to submit to the form
        var drawnItems;
        var store;
        map.on('map:loadfield', function (e) {
            drawnItems = e.field.drawnItems;
            store = e.field.store;
        });

        // Add the filelayer to allow the uploading of files
        control = L.Control.fileLayerLoad({
            // See http://leafletjs.com/reference.html#geojson-options
            layerOptions: {
                style: { color:'red' },
                //onEachFeature: function(feature){ drawnItems.addLayer(feature); },
            },

            // Add to map after loading (default: true) ?
            addToMap: false,
        });
        control.addTo(map);

        // When the fileLayer has loaded some data (i.e. someone has loaded a file)
        control.loader.on('data:loaded', function (e) {
            // Get the geojson layer which gets added from the file layers
            gLayer = e.layer.getLayers()[0];

            // If it's a KML it will have altitude, so iterate through and strip them out
            newLatLngs = []
            oldLatLngs = gLayer.getLatLngs();
            $(oldLatLngs).each(function(index, obj) {
                newLatLng = {lat: obj.lat, lng: obj.lng} // Can also: new L.LatLng(obj.lat, obj.lng);
                newLatLngs.push(newLatLng);
            })

            // Set the new latlngs for the polygon
            gLayer.setLatLngs(newLatLngs);

            // If someone has drawn something previously we need to wipe it
            drawnItems.eachLayer(function(l) {
                map.removeLayer(l);
            })
            drawnItems.clearLayers();

            // Add the polygon to the map, not sure why this is required but django-leaflet does this
            map.addLayer(gLayer)

            // Add the polygon to the drawnItems featureGroup
            drawnItems.addLayer(gLayer);

            // Django-leaflet does this so just copy it, it seems to make the fileLayer geojson 
            // get saved to the form
            store.save(drawnItems);
        });
    });
})
SBats commented 8 years ago

Hi @natoelgato ! Thank you for the feedback. I'm cleaning and improving a bit this plugin. Is this issue still relevant ? It it is, could you please provide a live example via a plunkr/ jsfiddle / codepen / ..., otherwise we can't help you. If not I will close this issue.