map / app /map_py_temp.py
atsuga's picture
Upload 40 files
6f10462 verified
import folium
import json
import random
import folium
import json
import os
import random
def generate_distinct_colors(n):
"""Generate n distinct bright colors for each district"""
# Predefined palette of 38 distinct, vibrant colors
colors = [
'#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8',
'#F7DC6F', '#BB8FCE', '#85C1E2', '#F8B739', '#52B788',
'#E63946', '#06FFA5', '#FFD93D', '#6BCF7F', '#C77DFF',
'#FF9F1C', '#2EC4B6', '#E71D36', '#FF499E', '#00B4D8',
'#90E0EF', '#F72585', '#7209B7', '#3A0CA3', '#F4A261',
'#2A9D8F', '#E76F51', '#264653', '#E9C46A', '#F77F00',
'#D62828', '#023047', '#8338EC', '#3DDC84', '#FF006E',
'#FFBE0B', '#FB5607', '#8AC926'
]
# Shuffle to ensure adjacent regions get different colors
random.shuffle(colors)
return colors[:n]
def create_map():
"""Create a Folium map with distinct colors for each kabupaten/kota in Jawa Timur.
Returns:
str: HTML string for embedding the Folium map (safe to render).
"""
# Load GeoJSON data - using complete kabupaten/kota file
geojson_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'geojson', 'jatim_kabkota.geojson')
with open(geojson_path, encoding='utf-8') as f:
geojson_data = json.load(f)
# Create a Folium map centered on Jawa Timur
m = folium.Map(
location=[-7.5, 112.5],
zoom_start=8,
tiles='CartoDB positron',
prefer_canvas=True,
zoom_control=True,
attributionControl=False
)
# Generate distinct colors for each kabupaten/kota (38 total)
num_features = len(geojson_data.get('features', []))
colors = generate_distinct_colors(num_features)
# Create color mapping with city names
color_map = {}
city_list = []
for idx, feature in enumerate(geojson_data.get('features', [])):
feature_name = feature.get('properties', {}).get('name', f'Feature_{idx}')
feature_type = feature.get('properties', {}).get('type', 'Kabupaten')
color_map[feature_name] = colors[idx]
city_list.append({
'name': feature_name,
'type': feature_type,
'color': colors[idx]
})
# Style function - 3D effect with vibrant colors like the reference image
def style_function(feature):
feature_name = feature['properties'].get('name', 'Unknown')
return {
'fillColor': color_map.get(feature_name, '#CCCCCC'),
'color': '#333333', # Dark gray border for 3D effect
'weight': 2, # Medium border
'fillOpacity': 1.0, # Completely solid for vibrant colors
'opacity': 1, # Solid border
'dashArray': None, # Solid line
'lineJoin': 'miter', # Sharp corners for clear boundaries
'lineCap': 'butt' # Clean edges
}
# Highlight function for hover
def highlight_function(feature):
return {
'fillColor': '#FFFF00', # Yellow on hover
'color': '#FF0000', # Red border
'weight': 3,
'fillOpacity': 0.9,
}
# Add GeoJSON layer with colored regions
folium.GeoJson(
geojson_data,
name='Jawa Timur',
style_function=style_function,
highlight_function=highlight_function,
tooltip=folium.GeoJsonTooltip(
fields=['name'],
aliases=['Wilayah:'],
localize=True,
sticky=False,
labels=True,
style="""
background-color: white;
border: 2px solid black;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 12px;
padding: 8px;
box-shadow: 3px 3px 5px rgba(0,0,0,0.5);
""",
)
).add_to(m)
# Add text labels on each kabupaten/kota
for feature in geojson_data.get('features', []):
props = feature.get('properties', {})
name = props.get('name', 'Unknown')
center_lat = props.get('centroid_lat')
center_lon = props.get('centroid_lon')
if center_lat and center_lon:
# Add label marker with white text and shadow for contrast
folium.Marker(
location=[center_lat, center_lon],
icon=folium.DivIcon(html=f'''
<div style="
font-family: Arial, sans-serif;
font-size: 10px;
color: #FFFFFF;
font-weight: bold;
text-shadow: 1px 1px 3px rgba(0,0,0,0.9),
-1px -1px 3px rgba(0,0,0,0.9),
1px -1px 3px rgba(0,0,0,0.9),
-1px 1px 3px rgba(0,0,0,0.9);
text-align: center;
white-space: nowrap;
">{name}</div>
''')
).add_to(m)
# Add custom CSS for STRONG 3D shadow effect like the reference image
custom_css = '''
<style>
.leaflet-container {
background-color: #F5F5F5 !important; /* Light gray background */
}
/* STRONG 3D shadow effect - multiple layers for depth */
.leaflet-interactive {
filter:
drop-shadow(3px 3px 2px rgba(0,0,0,0.3))
drop-shadow(6px 6px 4px rgba(0,0,0,0.25))
drop-shadow(9px 9px 8px rgba(0,0,0,0.2))
drop-shadow(12px 12px 12px rgba(0,0,0,0.15));
}
/* Clean polygon edges */
path.leaflet-interactive {
stroke-linejoin: miter !important;
stroke-linecap: butt !important;
}
</style>
'''
m.get_root().html.add_child(folium.Element(custom_css))
# Add legend showing all 38 kabupaten/kota with their unique colors
legend_html = '''
<div style="position: fixed;
bottom: 20px; left: 20px; width: 280px; max-height: 520px;
background-color: white; z-index:9999; font-size:11px;
border:2px solid #333; border-radius: 8px;
overflow-y: auto;
box-shadow: 5px 5px 15px rgba(0,0,0,0.5);
font-family: Arial, sans-serif;
">
<div style="background-color: #1976D2; color: white; padding: 12px;
font-weight: bold; text-align: center; font-size: 13px;
border-radius: 6px 6px 0 0;">
📍 38 Kabupaten/Kota Jawa Timur
</div>
<div style="padding: 10px; max-height: 450px; overflow-y: auto;">
'''
# Sort cities alphabetically and add to legend
sorted_cities = sorted(city_list, key=lambda x: x['name'])
for idx, city in enumerate(sorted_cities, 1):
legend_html += f'''
<div style="margin: 3px 0; display: flex; align-items: center;">
<div style="width: 20px; height: 20px; background-color: {city['color']};
border: 1.5px solid #333; margin-right: 8px; flex-shrink: 0;
border-radius: 3px;
box-shadow: 2px 2px 4px rgba(0,0,0,0.3);"></div>
<span style="font-size: 10px; color: #333;">
<b>{idx}.</b> {city['name']} ({city['type']})
</span>
</div>
'''
legend_html += '''
</div>
</div>
'''
m.get_root().html.add_child(folium.Element(legend_html))
# Add title
title_html = '''
<div style="position: fixed;
top: 10px; left: 50%; transform: translateX(-50%);
background-color: white; z-index:9999;
padding: 10px 30px;
border: 2px solid black;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;
box-shadow: 3px 3px 10px rgba(0,0,0,0.5);
">
Peta Jawa Timur - Kabupaten/Kota
</div>
'''
m.get_root().html.add_child(folium.Element(title_html))
# Return HTML representation
return m._repr_html_()