Draw Control Support in AnyMap¶
This notebook demonstrates how to use the draw control functionality with the MapLibre implementation in AnyMap. The draw control allows users to interactively draw and edit geometries on the map.
What is the Draw Control?¶
The draw control is based on mapbox-gl-draw and provides:
- Interactive drawing of points, lines, and polygons
- Editing and deleting existing geometries
- Loading existing GeoJSON data
- Retrieving drawn features as GeoJSON
- Programmatic control over drawing modes
Features¶
- ✅ Draw geometries: Points, lines, and polygons
- ✅ Edit geometries: Modify existing shapes
- ✅ Delete geometries: Remove unwanted features
- ✅ Load data: Import existing GeoJSON
- ✅ Export data: Get drawn features as GeoJSON
- ✅ Mode control: Switch between different drawing modes
- ✅ Event handling: React to drawing events
# Import required modules
from anymap import MapLibreMap
import json
print("AnyMap loaded successfully!")
print("Draw control support is built into the MapLibre implementation.")
AnyMap loaded successfully! Draw control support is built into the MapLibre implementation.
Example 1: Basic Draw Control¶
Let's start with a simple example of adding a draw control to the map.
# Create a map
m = MapLibreMap(
center=[40.7749, -122.4194], # San Francisco coordinates
zoom=12,
height="600px",
style="positron",
)
# Add draw control with default settings
m.add_draw_control()
print("Draw control added with default settings")
print("You can now draw points, lines, and polygons on the map!")
m
Draw control added with default settings You can now draw points, lines, and polygons on the map!
Instructions for the map above:
- Use the point tool (📍) to add points
- Use the line tool (📏) to draw lines
- Use the polygon tool (🔷) to draw polygons
- Use the trash tool (🗑️) to delete selected features
- Click and drag to select and move features
Example 2: Custom Draw Control Configuration¶
You can customize which drawing tools are available and where the control is positioned.
# Create a new map for custom configuration
m2 = MapLibreMap(
center=[40.7749, -122.4194], zoom=13, height="600px", style="dark-matter"
)
# Add draw control with custom configuration
m2.add_draw_control(
position="top-right", # Position the control on the top-right
controls={
"point": True, # Enable point drawing
"line_string": False, # Disable line drawing
"polygon": True, # Enable polygon drawing
"trash": True, # Enable delete tool
},
default_mode="draw_polygon", # Start in polygon drawing mode
keybindings=True, # Enable keyboard shortcuts
touch_enabled=True, # Enable touch interactions
)
print("Custom draw control added:")
print("- Position: top-right")
print("- Tools: points and polygons only")
print("- Default mode: polygon drawing")
m2
Custom draw control added: - Position: top-right - Tools: points and polygons only - Default mode: polygon drawing
Example 3: Loading Existing GeoJSON Data¶
You can load existing GeoJSON data into the draw control for editing.
# Create sample GeoJSON data
sample_geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.4194, 37.7749]},
"properties": {"name": "San Francisco City Hall", "type": "landmark"},
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[-122.4200, 37.7700],
[-122.4150, 37.7700],
[-122.4150, 37.7750],
[-122.4200, 37.7750],
[-122.4200, 37.7700],
]
],
},
"properties": {"name": "Sample Area", "type": "area"},
},
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-122.4180, 37.7720],
[-122.4160, 37.7740],
[-122.4140, 37.7730],
],
},
"properties": {"name": "Sample Route", "type": "route"},
},
],
}
# Create a new map
m3 = MapLibreMap(center=[37.7749, -122.4194], zoom=14, height="600px", style="voyager")
# Add draw control
m3.add_draw_control(position="top-left")
# Load the sample GeoJSON data
m3.load_draw_data(sample_geojson)
print("Loaded sample GeoJSON data:")
print("- 1 Point (City Hall)")
print("- 1 Polygon (Sample Area)")
print("- 1 LineString (Sample Route)")
print("\nYou can now edit these existing features or draw new ones!")
m3
Loaded sample GeoJSON data: - 1 Point (City Hall) - 1 Polygon (Sample Area) - 1 LineString (Sample Route) You can now edit these existing features or draw new ones!
Example 4: Retrieving Draw Data¶
You can retrieve the currently drawn features as GeoJSON.
# Note: In a real Jupyter environment, you would draw some features on the map above
# then run this cell to get the drawn data
# Trigger retrieval of draw data
draw_data = m3.get_draw_data()
# The actual data will be available in the _draw_data trait
print("Draw data retrieval triggered.")
print("In a real environment, drawn features would be available in m3._draw_data")
# You can also access it directly (this will be empty until features are drawn)
current_draw_data = m3._draw_data
print(f"Current draw data: {current_draw_data}")
Draw data retrieval triggered. In a real environment, drawn features would be available in m3._draw_data Current draw data: {'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-122.4194, 37.7749]}, 'properties': {'name': 'San Francisco City Hall', 'type': 'landmark'}}, {'type': 'Feature', 'geometry': {'type': 'Polygon', 'coordinates': [[[-122.42, 37.77], [-122.415, 37.77], [-122.415, 37.775], [-122.42, 37.775], [-122.42, 37.77]]]}, 'properties': {'name': 'Sample Area', 'type': 'area'}}, {'type': 'Feature', 'geometry': {'type': 'LineString', 'coordinates': [[-122.418, 37.772], [-122.416, 37.774], [-122.414, 37.773]]}, 'properties': {'name': 'Sample Route', 'type': 'route'}}]}
Example 5: Draw Control Mode Management¶
You can programmatically control the drawing mode.
# Set different drawing modes
print("Available drawing modes:")
print("- simple_select: Select and edit features")
print("- direct_select: Edit vertices of selected features")
print("- draw_point: Draw points")
print("- draw_line_string: Draw lines")
print("- draw_polygon: Draw polygons")
print("- static: Disable all interactions")
# Set the draw mode to polygon drawing
m3.set_draw_mode("draw_polygon")
print("\n✓ Set mode to polygon drawing")
# You can change modes programmatically
print("\nTry drawing a polygon, then run the next cell to switch to point mode")
Available drawing modes: - simple_select: Select and edit features - direct_select: Edit vertices of selected features - draw_point: Draw points - draw_line_string: Draw lines - draw_polygon: Draw polygons - static: Disable all interactions ✓ Set mode to polygon drawing Try drawing a polygon, then run the next cell to switch to point mode
# Switch to point drawing mode
m3.set_draw_mode("draw_point")
print("✓ Switched to point drawing mode")
✓ Switched to point drawing mode
Example 6: Clearing and Deleting Features¶
You can clear all drawn features or delete specific ones.
# Create a map with some initial data for demonstration
m4 = MapLibreMap(center=[37.7749, -122.4194], zoom=13, height="600px", style="streets")
# Add draw control
m4.add_draw_control()
# Load some test data
test_data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.4194, 37.7749]},
"properties": {"name": "Point 1"},
},
{
"type": "Feature",
"geometry": {"type": "Point", "coordinates": [-122.4150, 37.7700]},
"properties": {"name": "Point 2"},
},
],
}
m4.load_draw_data(test_data)
print("Loaded test data with 2 points")
print("Try drawing some additional features, then run the cell below to test deletion")
m4
Loaded test data with 2 points Try drawing some additional features, then run the cell below to test deletion
# Clear all drawn features
m4.clear_draw_data()
print("✓ Cleared all drawn features")
# Note: In a real scenario, you could also delete specific features by ID:
# m4.delete_draw_features(['feature_id_1', 'feature_id_2'])
print("\nTo delete specific features, you would use:")
print("m4.delete_draw_features(['feature_id_1', 'feature_id_2'])")
✓ Cleared all drawn features To delete specific features, you would use: m4.delete_draw_features(['feature_id_1', 'feature_id_2'])
Example 7: Export Map with Draw Control to HTML¶
Maps with draw controls can be exported to standalone HTML files.
# Create a final map for HTML export
export_map = MapLibreMap(
center=[37.7749, -122.4194], zoom=12, height="600px", style="satellite"
)
# Add draw control
export_map.add_draw_control(
position="top-right",
controls={"point": True, "line_string": True, "polygon": True, "trash": True},
)
# Load some sample data
export_map.load_draw_data(sample_geojson)
# Export to HTML
export_map.to_html(
"san_francisco_draw_map.html", title="San Francisco Draw Control Demo"
)
print("Map exported to 'san_francisco_draw_map.html'")
print(
"The HTML file includes draw control functionality and can be opened in any browser"
)
export_map
Map exported to 'san_francisco_draw_map.html' The HTML file includes draw control functionality and can be opened in any browser
Summary¶
This notebook demonstrated the draw control functionality in AnyMap:
✅ Key Features Covered:¶
- Basic Draw Control: Simple addition of draw tools to the map
- Custom Configuration: Customizing available tools, position, and behavior
- Loading Data: Importing existing GeoJSON data for editing
- Retrieving Data: Getting drawn features as GeoJSON
- Mode Management: Programmatically controlling drawing modes
- Data Management: Clearing and deleting features
- HTML Export: Exporting maps with draw controls to HTML
🔧 Method Signatures:¶
# Add draw control
map.add_draw_control(
position: str = "top-left",
controls: Optional[Dict[str, bool]] = None,
default_mode: str = "simple_select",
keybindings: bool = True,
touch_enabled: bool = True
)
# Load GeoJSON data
map.load_draw_data(geojson_data: Union[Dict, str])
# Get drawn data
map.get_draw_data() -> Dict
# Clear all features
map.clear_draw_data()
# Delete specific features
map.delete_draw_features(feature_ids: List[str])
# Set drawing mode
map.set_draw_mode(mode: str)
🎨 Drawing Modes:¶
- simple_select: Select and move features
- direct_select: Edit feature vertices
- draw_point: Draw points
- draw_line_string: Draw lines
- draw_polygon: Draw polygons
- static: Disable all interactions
🎯 Use Cases:¶
- Annotation: Mark important locations or areas
- Planning: Draw routes, boundaries, or zones
- Data Collection: Gather spatial information interactively
- Editing: Modify existing spatial data
- Measurement: Create geometries for area/distance calculations
The draw control integration provides a powerful way to create interactive mapping applications with drawing and editing capabilities!