Skip to content

Commit a3c6994

Browse files
authored
Merge pull request #720 from ocefpaf/Draw
add Draw plugin
2 parents 9cb3b1f + af7c98d commit a3c6994

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed

CHANGES.txt

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
0.5.0
2+
~~~~~
3+
4+
- Added `Draw` plugin (ocefpaf #720)
5+
- Better handling of URL input (ocefpaf #717)
6+
- Versioned docs! Visit http://python-visualization.github.io/folium/docs-v{{version}}
7+
or simply http://python-visualization.github.io/folium/ for the latest version.
8+
9+
Bug Fixes
10+
11+
- Fix `VideoOverlay` import (ocefpaf #719)
12+
- Fix `choropleth` docstring (lsetiawan #713)
13+
- Fix `choropleth` name in `LayerControl` (ocefpaf #493)
14+
115
0.4.0
216
~~~~~
317
- Optional `iconCreateFunction` for `MarkerCluster` to customize the icons (odovad #701)

examples/Draw.ipynb

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"metadata": {},
7+
"outputs": [
8+
{
9+
"name": "stdout",
10+
"output_type": "stream",
11+
"text": [
12+
"0.4.0+15.ga36370e\n"
13+
]
14+
}
15+
],
16+
"source": [
17+
"import os\n",
18+
"import folium\n",
19+
"\n",
20+
"\n",
21+
"print(folium.__version__)"
22+
]
23+
},
24+
{
25+
"cell_type": "code",
26+
"execution_count": 2,
27+
"metadata": {},
28+
"outputs": [
29+
{
30+
"data": {
31+
"text/html": [
32+
"<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVMgPSBmYWxzZTsgTF9OT19UT1VDSCA9IGZhbHNlOyBMX0RJU0FCTEVfM0QgPSBmYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2FqYXguZ29vZ2xlYXBpcy5jb20vYWpheC9saWJzL2pxdWVyeS8xLjExLjEvanF1ZXJ5Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS4yLjAvZGlzdC9sZWFmbGV0LmNzcyIgLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC5taW4uY3NzIiAvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiIC8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIgLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuY3NzIiAvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2dpdC5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIiAvPgogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIAogICAgICAgICAgICA8c3R5bGU+ICNtYXBfMjJmOWVhOGVlOTk0NDJkZDg1ZjhmYTAwOGFiMWFkNTAgewogICAgICAgICAgICAgICAgcG9zaXRpb24gOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgIHdpZHRoIDogMTAwLjAlOwogICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLnJhd2dpdC5jb20vTGVhZmxldC9MZWFmbGV0LmRyYXcvdjAuNC4xMi9kaXN0L2xlYWZsZXQuZHJhdy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLnJhd2dpdC5jb20vTGVhZmxldC9MZWFmbGV0LmRyYXcvdjAuNC4xMi9kaXN0L2xlYWZsZXQuZHJhdy5jc3MiIC8+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4ucmF3Z2l0LmNvbS9MZWFmbGV0L0xlYWZsZXQuZHJhdy92MC40LjEyL2Rpc3QvbGVhZmxldC5kcmF3LmpzIj48L3NjcmlwdD4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG4ucmF3Z2l0LmNvbS9MZWFmbGV0L0xlYWZsZXQuZHJhdy92MC40LjEyL2Rpc3QvbGVhZmxldC5kcmF3LmNzcyIgLz4KPC9oZWFkPgo8Ym9keT4gICAgCiAgICAKICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF8yMmY5ZWE4ZWU5OTQ0MmRkODVmOGZhMDA4YWIxYWQ1MCIgPjwvZGl2PgogICAgICAgIAo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCgogICAgICAgICAgICAKICAgICAgICAgICAgICAgIHZhciBib3VuZHMgPSBudWxsOwogICAgICAgICAgICAKCiAgICAgICAgICAgIHZhciBtYXBfMjJmOWVhOGVlOTk0NDJkZDg1ZjhmYTAwOGFiMWFkNTAgPSBMLm1hcCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdtYXBfMjJmOWVhOGVlOTk0NDJkZDg1ZjhmYTAwOGFiMWFkNTAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge2NlbnRlcjogWzAsMF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6b29tOiAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcnM6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl9mMzI0NWFjMjAyZWE0MTI3YmNjMjBlYTFjYjJlOTJmMSA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJywKICAgICAgICAgICAgICAgIHsKICAiYXR0cmlidXRpb24iOiBudWxsLAogICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAibWF4Wm9vbSI6IDE4LAogICJtaW5ab29tIjogMSwKICAibm9XcmFwIjogZmFsc2UsCiAgInN1YmRvbWFpbnMiOiAiYWJjIgp9CiAgICAgICAgICAgICAgICApLmFkZFRvKG1hcF8yMmY5ZWE4ZWU5OTQ0MmRkODVmOGZhMDA4YWIxYWQ1MCk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgLy8gRmVhdHVyZUdyb3VwIGlzIHRvIHN0b3JlIGVkaXRhYmxlIGxheWVycy4KICAgICAgICAgICAgdmFyIGRyYXduSXRlbXMgPSBuZXcgTC5mZWF0dXJlR3JvdXAoKS5hZGRUbyhtYXBfMjJmOWVhOGVlOTk0NDJkZDg1ZjhmYTAwOGFiMWFkNTApOwogICAgICAgICAgICB2YXIgZHJhd19jb250cm9sXzYyNjI1OTA3NmMxODQzMzJhYjBiYmIxZmU4MGJlNzE3ID0gbmV3IEwuQ29udHJvbC5EcmF3KHsKICAgICAgICAgICAgICAgICJlZGl0IjogeyJmZWF0dXJlR3JvdXAiOiBkcmF3bkl0ZW1zfQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIG1hcF8yMmY5ZWE4ZWU5OTQ0MmRkODVmOGZhMDA4YWIxYWQ1MC5hZGRDb250cm9sKGRyYXdfY29udHJvbF82MjYyNTkwNzZjMTg0MzMyYWIwYmJiMWZlODBiZTcxNyk7CiAgICAgICAgICAgIG1hcF8yMmY5ZWE4ZWU5OTQ0MmRkODVmOGZhMDA4YWIxYWQ1MC5vbihMLkRyYXcuRXZlbnQuQ1JFQVRFRCwgZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgICAgdmFyIGxheWVyID0gZXZlbnQubGF5ZXIsCiAgICAgICAgICAgICAgICAgIHR5cGUgPSBldmVudC5sYXllclR5cGUsCiAgICAgICAgICAgICAgICAgIGNvb3JkczsKICAgICAgICAgICAgICB2YXIgY29vcmRzID0gSlNPTi5zdHJpbmdpZnkobGF5ZXIudG9HZW9KU09OKCkpOwogICAgICAgICAgICAgIGxheWVyLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgYWxlcnQoY29vcmRzKTsKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGNvb3Jkcyk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgZHJhd25JdGVtcy5hZGRMYXllcihsYXllcik7CiAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
33+
],
34+
"text/plain": [
35+
"<folium.folium.Map at 0x7f10abc787f0>"
36+
]
37+
},
38+
"execution_count": 2,
39+
"metadata": {},
40+
"output_type": "execute_result"
41+
}
42+
],
43+
"source": [
44+
"from folium.plugins import Draw\n",
45+
"\n",
46+
"m = folium.Map()\n",
47+
"\n",
48+
"draw = Draw()\n",
49+
"\n",
50+
"draw.add_to(m)\n",
51+
"\n",
52+
"m.save(os.path.join('results', 'Draw.html'))\n",
53+
"\n",
54+
"m"
55+
]
56+
}
57+
],
58+
"metadata": {
59+
"kernelspec": {
60+
"display_name": "Python 3",
61+
"language": "python",
62+
"name": "python3"
63+
},
64+
"language_info": {
65+
"codemirror_mode": {
66+
"name": "ipython",
67+
"version": 3
68+
},
69+
"file_extension": ".py",
70+
"mimetype": "text/x-python",
71+
"name": "python",
72+
"nbconvert_exporter": "python",
73+
"pygments_lexer": "ipython3",
74+
"version": "3.6.2"
75+
}
76+
},
77+
"nbformat": 4,
78+
"nbformat_minor": 2
79+
}

folium/plugins/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from __future__ import (absolute_import, division, print_function)
1212

1313
from folium.plugins.boat_marker import BoatMarker
14+
from folium.plugins.draw import Draw
1415
from folium.plugins.fast_marker_cluster import FastMarkerCluster
1516
from folium.plugins.float_image import FloatImage
1617
from folium.plugins.fullscreen import Fullscreen
@@ -28,6 +29,7 @@
2829

2930
__all__ = [
3031
'BoatMarker',
32+
'Draw',
3133
'FastMarkerCluster',
3234
'FloatImage',
3335
'Fullscreen',

folium/plugins/draw.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import (absolute_import, division, print_function)
4+
5+
from branca.element import CssLink, Figure, JavascriptLink, MacroElement
6+
7+
from jinja2 import Template
8+
9+
10+
class Draw(MacroElement):
11+
"""
12+
Vector drawing and editing plugin for Leaflet.
13+
14+
Examples
15+
--------
16+
>>> m = folium.Map()
17+
>>> Draw().draw.add_to(m)
18+
19+
For more info please check
20+
https://leaflet.github.io/Leaflet.draw/docs/leaflet-draw-latest.html
21+
22+
"""
23+
def __init__(self):
24+
super(Draw, self).__init__()
25+
self._name = 'DrawControl'
26+
27+
self._template = Template(u"""
28+
{% macro script(this, kwargs) %}
29+
// FeatureGroup is to store editable layers.
30+
var drawnItems = new L.featureGroup().addTo({{this._parent.get_name()}});
31+
var {{this.get_name()}} = new L.Control.Draw({
32+
"edit": {"featureGroup": drawnItems}
33+
});
34+
{{this._parent.get_name()}}.addControl({{this.get_name()}});
35+
{{this._parent.get_name()}}.on(L.Draw.Event.CREATED, function (event) {
36+
var layer = event.layer,
37+
type = event.layerType,
38+
coords;
39+
var coords = JSON.stringify(layer.toGeoJSON());
40+
layer.on('click', function() {
41+
alert(coords);
42+
console.log(coords);
43+
});
44+
drawnItems.addLayer(layer);
45+
});
46+
{% endmacro %}
47+
""")
48+
49+
def render(self, **kwargs):
50+
super(Draw, self).render()
51+
52+
figure = self.get_root()
53+
assert isinstance(figure, Figure), ('You cannot render this Element '
54+
'if it is not in a Figure.')
55+
56+
figure.header.add_child(
57+
JavascriptLink('https://cdn.rawgit.com/Leaflet/Leaflet.draw/v0.4.12/dist/leaflet.draw.js')) # noqa
58+
59+
figure.header.add_child(
60+
CssLink('https://cdn.rawgit.com/Leaflet/Leaflet.draw/v0.4.12/dist/leaflet.draw.css')) # noqa

0 commit comments

Comments
 (0)