Leaflet.draw mapping: How to initiate the draw function without toolbar?

30,298

Solution 1

This simple code works for me:

new L.Draw.Polyline(map, drawControl.options.polyline).enable();

Just put it into the onclick handler of your custom button (or wherever you want).

The variables map and drawControl are references to your leaflet map and draw control.

Diving into the source code (leaflet.draw-src.js) you can find the functions to draw the other elements and to edit or delete them.

new L.Draw.Polygon(map, drawControl.options.polygon).enable()
new L.Draw.Rectangle(map, drawControl.options.rectangle).enable()
new L.Draw.Circle(map, drawControl.options.circle).enable()
new L.Draw.Marker(map, drawControl.options.marker).enable()

new L.EditToolbar.Edit(map, {
                featureGroup: drawControl.options.featureGroup,
                selectedPathOptions: drawControl.options.edit.selectedPathOptions
            })
new L.EditToolbar.Delete(map, {
                featureGroup: drawControl.options.featureGroup
            })

I hope this will be useful for you too.

EDIT: The L.EditToolbar.Edit and L.EditToolbar.Delete classes expose the following useful methods:

  • enable(): to start edit/delete mode
  • disable(): to return to standard mode
  • save(): to save changes (it fires draw:edited / draw:deleted events)
  • revertLayers(): to undo changes

Solution 2

I think it's worth mentioning Jacob Toyes answer to this problem. You're always drawing with handlers in leaflet.draw - not directly with layers. If you want to edit a layer, you use the handler saved in a layers editing field like that: layer.editing.enable();. And if you want to create a new layer, you first create a new handler:

// Define you draw handler somewhere where you click handler can access it. N.B. pass any draw options into the handler
var polygonDrawer = new L.Draw.Polyline(map);

// Assumming you have a Leaflet map accessible
map.on('draw:created', function (e) {
    var type = e.layerType,
        layer = e.layer;

    // Do whatever you want with the layer.
    // e.type will be the type of layer that has been draw (polyline, marker, polygon, rectangle, circle)
    // E.g. add it to the map
    layer.addTo(map);
});

// Click handler for you button to start drawing polygons
$('#draw_poly').click(function() {
    polygonDrawer.enable();
});

By now there actually is an example on the leaflet.draw github page: https://github.com/Leaflet/Leaflet.draw/blob/develop/docs/examples/edithandlers.html

Nevertheless I think handlers aren't well documented there yet.

Like stated above, L.EditToolbar.Edit and L.EditToolbar.Delete expose interesting methods and events like editstart and editstop. What's not mentioned is that these two classes themselves are derived from L.Handler.

Solution 3

So I've figured this out for circles, but it should be the same for polygons. It's actually really simple. Hopefully the following code answers your question, but if not let me know and I can post more to a gist or something.

// Creates the circle on the map for the given latLng and Radius
// If the createdWithAddress flag is true, the circle will not update 
// it's address according to its position. 
createCircle: function(latLng, radius, createdWithAddress) {
if (!this.circle) {
  var self = this,
      centerIcon,
      centerMarker;

  centerIcon = new L.Icon({
    iconUrl: '/assets/location_pin_24px.png',
    iconSize: [24, 24],
    iconAnchor: [12, 24],
    shadowUrl: '/assets/marker-shadow.png',
    shadowSize: [20, 20],
    shadowAnchor:[6, 20]
  })

  // Setup the options for the circle -> Override icons, immediately editable
  options = {
    stroke: true,
    color: '#333333',
    opacity: 1.0,
    weight: 4,
    fillColor: '#FFFFFF',
    moveIcon: centerIcon,
    resizeIcon: new L.Icon({
      iconUrl: '/assets/radius_handle_18px.png',
      iconSize: [12, 12],
      iconAnchor: [0,0]
    })
  }

  if (someConfigVarYouDontNeedToKnow) {
    options.editable = false
    centerMarker = new L.Marker(latLng, { icon:centerIcon })
  } else {
    options.editable = true
  }

  // Create our location circle 
  // NOTE: I believe I had to modify Leaflet or Leaflet.draw to allow for passing in
  // options, but you can make it editable with circle.editing.enable()
  this.circle = L.circle([latLng.lat, latLng.lng], radius, options)

  // Add event handlers to update the location
  this.circle.on('add', function() {
    if (!createdWithAddress) {
      self.reverseGeocode(this.getLatLng())
    }
    self.updateCircleLocation(this.getLatLng(), this.getRadius())
    self.updateMapView()
  })            
  this.circle.on('edit', function() {
    if (self.convertLatLngToString(this.getLatLng()) !== self.getLocationLatLng()) {
      self.reverseGeocode(this.getLatLng())
    }
    self.updateCircleLocation(this.getLatLng(), this.getRadius())
    self.updateMapView()
  })

  this.map.addLayer(this.circle)
  if (centerMarker) {
    centerMarker.addTo(this.map)
    this.circle.redraw()
    centerMarker.update()
  }
}
},

Sorry a lot of that is just noise, but it should give you an idea of how to go about this. You can control editing like you said with editing.enable()/.disable().

Make sure to comment with any questions. Good luck man.

Solution 4

While BaCH's solution is propably the best, I would like to add a one-liner solution which is actually more future-proof (than digging into undocumented Leaflet Draw methods) and the simplest.

document.querySelector('.leaflet-draw-draw-polygon').click();

That's it. You just take andvantage of the existance of the toolbar but actually, you do not use it. You can initiate drawing programmatically in any way. And you can also hide the toolbar using CSS.

In case you want to initiate drawing of a different shape, use one of the following classes:

.leaflet-draw-draw-polyline
.leaflet-draw-draw-rectangle
.leaflet-draw-draw-circle
.leaflet-draw-draw-marker
.leaflet-draw-draw-circlemarker
Share:
30,298

Related videos on Youtube

Sam
Author by

Sam

Hi, I'm Sam. I'm a software engineer.

Updated on July 09, 2022

Comments

  • Sam
    Sam almost 2 years

    For anyone experienced with leaflet or leaflet.draw plugin:

    I want to initiate drawing a polygon without using the toolbar from leaflet.draw. I've managed to find the property that allows editing without using the toolbar (layer.editing.enable();) by searching online (it's not in the main documentation). I can't seem to find how to begin drawing a polygon without the toolbar button. Any help would be much appreciated!

    Thank you :)

    • Gowiem
      Gowiem almost 11 years
      I need to figure this out as well. If you found the answer please post it here, Thanks.
    • Sam
      Sam almost 11 years
      I have yet to find the answer myself.
    • Ground Hog
      Ground Hog about 10 years
      See this question for a simple working demo: stackoverflow.com/questions/22730888/…
  • Sam
    Sam almost 11 years
    Thanks mate. Much appreciated.
  • Sam
    Sam almost 11 years
    Thanks mate, much appreciated. I had given up and decided to tell the user when to click the toolbar. I'll go back to this and refactor my page :)
  • Ruut
    Ruut about 10 years
    If you want to know how to programmatically create a marker which can be edited with leaflet.draw, see: github.com/Leaflet/Leaflet.draw/issues/159
  • Marty.H
    Marty.H about 9 years
    Is it possible to use this method to create polygons with different styling? ie one button creates a green polygon, another creates a blue one. If so, how would you go about doing that?
  • BaCH
    BaCH about 9 years
    Yes, you can pass as 2nd parameter of L.Draw.* different sets of options. Here is the reference for the option parameter: github.com/Leaflet/Leaflet.draw#draw-handler-options. The property you need to set is "shapeOptions"
  • Es Noguera
    Es Noguera about 6 years
    Can I listen click events from vertex Without using the Draw toolbar?
  • Nika Kurashvili
    Nika Kurashvili almost 5 years
    Hey @schmijos, I can't seem to make this work. I copied your code but when i finish drawing, i can't edit it. what do I add to your code so that I can edit?
  • schmijos
    schmijos almost 5 years
    Hi @NikaKhurashvili, sorry I'm totally out of this context by now. I'd suggest that you ask a SO question of your own telling what you've tried already.
  • JohnGIS
    JohnGIS almost 5 years
    Life saver! Only weird issue is that I am no longer seeing the area when drawing a polygon.
  • Rayann Nayran
    Rayann Nayran over 3 years
    I Did not figure out how to get the drawControl variable, could you give an example?
  • BaCH
    BaCH over 3 years
    @RayannNayran drawControl is an object of the class L.Control.Draw defined by the plugin Leaflet.draw. You can simply create it as: var drawControl = new L.Control.Draw(options); Here is an example: github.com/Leaflet/Leaflet.draw
  • Gil Epshtain
    Gil Epshtain over 2 years
    Why do I need to create a new object - new L.Draw.Polygon(...) for changing the existing object drawControl? Should I store this new object? can I reuse it or should I just create a new one each time? This entire method looks strange to me
  • Gil Epshtain
    Gil Epshtain over 2 years
    Great answer, I would add that instead of querying the document. Get the map-element from the mapHandler. const mapHandler: L.Map = ...; mapHandler.getContainer().querySelector<HTMLButtonElement>('‌​.leaflet-draw-draw-p‌​olygon').click();
  • BaCH
    BaCH over 2 years
    @GilEpshtain L.Draw.Polygon(...) is the class that controls tha polygon drawing; you can instantiate it and store the reference to call the enable() method whenever you need to start the drawing of another polygon. The other lines of code are just for reference, in case you need to draw other shapes.