from branca.element import MacroElement from folium.elements import JSCSSMixin from folium.template import Template class Draw(JSCSSMixin, MacroElement): ''' Vector drawing and editing plugin for Leaflet. Parameters ---------- export : bool, default False Add a small button that exports the drawn shapes as a geojson file. feature_group : FeatureGroup, optional The FeatureGroup object that will hold the editable figures. This can be used to initialize the Draw plugin with predefined Layer objects. filename : string, default 'data.geojson' Name of geojson file position : {'topleft', 'toprigth', 'bottomleft', 'bottomright'} Position of control. See https://leafletjs.com/reference.html#control show_geometry_on_click : bool, default True When True, opens an alert with the geometry description on click. draw_options : dict, optional The options used to configure the draw toolbar. See http://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html#drawoptions edit_options : dict, optional The options used to configure the edit toolbar. See https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html#editpolyoptions on : dict, optional Event handlers to attach to the created layer. Pass a mapping from the names of the events to their `JsCode` handlers. Examples -------- >>> m = folium.Map() >>> Draw( ... export=True, ... filename="my_data.geojson", ... show_geometry_on_click=False, ... position="topleft", ... draw_options={"polyline": {"allowIntersection": False}}, ... edit_options={"poly": {"allowIntersection": False}}, ... on={ ... "click": JsCode( ... """ ... function(event) { ... alert(JSON.stringify(this.toGeoJSON())); ... } ... """ ... ) ... }, ... ).add_to(m) For more info please check https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html ''' _template = Template( """ {% macro html(this, kwargs) %} {% if this.export %} Export {% endif %} {% endmacro %} {% macro script(this, kwargs) %} var options = { position: {{ this.position|tojson }}, draw: {{ this.draw_options|tojson }}, edit: {{ this.edit_options|tojson }}, } {%- if this.feature_group %} var drawnItems_{{ this.get_name() }} = {{ this.feature_group.get_name() }}; {%- else %} // FeatureGroup is to store editable layers. var drawnItems_{{ this.get_name() }} = new L.featureGroup().addTo( {{ this._parent.get_name() }} ); {%- endif %} options.edit.featureGroup = drawnItems_{{ this.get_name() }}; var {{ this.get_name() }} = new L.Control.Draw( options ).addTo( {{this._parent.get_name()}} ); {{ this._parent.get_name() }}.on(L.Draw.Event.CREATED, function(e) { var layer = e.layer, type = e.layerType; var coords = JSON.stringify(layer.toGeoJSON()); {%- if this.show_geometry_on_click %} layer.on('click', function() { alert(coords); console.log(coords); }); {%- endif %} {%- for event, handler in this.on.items() %} layer.on( "{{event}}", {{handler}} ); {%- endfor %} drawnItems_{{ this.get_name() }}.addLayer(layer); }); {{ this._parent.get_name() }}.on('draw:created', function(e) { drawnItems_{{ this.get_name() }}.addLayer(e.layer); }); {% if this.export %} document.getElementById('export').onclick = function(e) { var data = drawnItems_{{ this.get_name() }}.toGeoJSON(); var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data)); document.getElementById('export').setAttribute( 'href', 'data:' + convertedData ); document.getElementById('export').setAttribute( 'download', {{ this.filename|tojson }} ); } {% endif %} {% endmacro %} """ ) default_js = [ ( "leaflet_draw_js", "https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js", ) ] default_css = [ ( "leaflet_draw_css", "https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css", ) ] def __init__( self, export=False, feature_group=None, filename="data.geojson", position="topleft", show_geometry_on_click=True, draw_options=None, edit_options=None, on=None, ): super().__init__() self._name = "DrawControl" self.export = export self.feature_group = feature_group self.filename = filename self.position = position self.show_geometry_on_click = show_geometry_on_click self.draw_options = draw_options or {} self.edit_options = edit_options or {} self.on = on or {}