Quickstart#
Elevate your Folium maps with professional-grade interactive plugins. foliplus provides advanced Layer Management, Dynamic H3 Heatmaps, Spatial Measurement tools, and unified search capabilities in a single, easy-to-use toolkit.
What you will learn#
Building a multi-theme base map.
Preparing spatially-valid datasets using GeoPandas.
Integrating the full suite of foliplus plugins.
Exporting interactive maps for production use.
1. Installation#
Install the core package via pip:
$ pip install -U foliplus
For the spatial analysis used in this guide, we recommend:
$ pip install -U my-data-toolkit geopandas
Note: Please restart your notebook kernel after installing new packages.
2. Data Preparation & Base Map#
To fully demonstrate the power of foliplus, weโll prepare a multi-layered urban dataset:
Administrative Context: Loading district boundaries (Polygons) to provide spatial grounding.
Point Density: Generating a synthetic grid of facility points with numeric
scoreweights.Symbolic Landmarks: Identifying district centers with custom icons to showcase how
LayerControlautomatically identifies geometry types.Base Themes: Setting up both Light and Dark modes for different visualization needs.
import dtoolkit.geoaccessor # noqa: F401
import folium
import geopandas as gpd
import numpy as np
import pandas as pd
# ---------------------------------------------------------------------------
# 1. Load & Refine Administrative Boundaries
# ---------------------------------------------------------------------------
# Load the Shanghai district boundaries
boundary = gpd.read_file("data/gadm41_CHN_3_Shanghai.geojson")
# Calculate District Centers (Layer 1)
# Re-project to EPSG:3857 for accurate geometry centers, then back to EPSG:4326 for Folium
districts = boundary.copy()
districts["geometry"] = boundary.to_crs(3857).centroid.to_crs(4326)
# Inject simulated demographic data for visualization
np.random.seed(42)
districts["population_density"] = np.random.randint(5000, 30000, len(districts))
# ---------------------------------------------------------------------------
# 2. Vectorized Point Sampling (Layer 2)
# ---------------------------------------------------------------------------
bounds = boundary.total_bounds
facilities = (
# Generate a dense candidate pool across the city
pd.DataFrame(
{
"x": np.random.uniform(bounds[0], bounds[2], 5000),
"y": np.random.uniform(bounds[1], bounds[3], 5000),
"score": np.random.randint(1, 100, 5000),
}
)
.from_xy("x", "y", crs=4326)
# Perform spatial join to keep only points inside the land area
.sjoin(boundary, how="inner")
.groupby("NAME_3")
.sample(n=50, random_state=42, replace=True)
.reset_index(drop=True)
)
# ---------------------------------------------------------------------------
# 3. Initialize Base Map
# ---------------------------------------------------------------------------
center = districts.geocentroid()
m = folium.Map(location=[center.y, center.x], zoom_start=10, tiles=None)
# Add professional base themes
folium.TileLayer("CartoDB positron", name="Light Canvas").add_to(m)
folium.TileLayer("CartoDB dark_matter", name="Dark Mode", show=False).add_to(m)
# ---------------------------------------------------------------------------
# 4. Layer Orchestration
# ---------------------------------------------------------------------------
# Step 1: Add District Landmarks (Top markers)
districts.explore(
m=m,
name="District Landmarks",
marker_type="marker",
marker_kwds={"icon": folium.Icon(color="cadetblue", icon="map-pin", prefix="fa")},
tooltip="NAME_3",
popup=["NAME_3", "population_density"],
legend=False,
)
# Step 2: Add Facility Points (Heatmap source)
facilities.explore(
m=m,
name="Facility Points",
column="score",
cmap="plasma",
marker_type="circle_marker",
style_kwds={"radius": 3, "fillOpacity": 0.8, "stroke": False},
legend=True,
)
# Step 3: Add Administrative Polygons as the base overlay
boundary.explore(
m=m,
name="Municipal Boundaries",
color="gray",
style_kwds={"fillOpacity": 0.05, "weight": 1.5, "dashArray": "5, 5"},
tooltip="NAME_3",
popup=True,
legend=False,
)
print(
f"๐ฆ Geo-Engine Ready: Orchestrating {len(facilities)} points across {len(districts)} districts."
)
ERROR 1: PROJ: proj_create_from_database: Open of /home/docs/checkouts/readthedocs.org/user_builds/foliplus/conda/latest/share/proj failed
Matplotlib is building the font cache; this may take a moment.
๐ฆ Geo-Engine Ready: Orchestrating 600 points across 12 districts.
3. Enable foliplus Plugins#
Now, we activate the professional toolkit. Observe how the plugins interact with our data:
LayerControl: Allows real-time reordering of layers and quick adjustments to transparency or base themes.HeatmapControl: Aggregates facility points into H3 hexagons. Weโve configured it to use thesumof thescorefield for a weighted density analysis.MapSearch: Provides a unified interface for coordinate jumping and keyword search (e.g., search for โPudongโ).MeasureControl: Precision tools for distance and area measurements directly on the map.Fullscreen: A distraction-free mode for presentations and data exploration.
from foliplus import (
Fullscreen,
HeatmapControl,
LayerControl,
MapSearch,
MeasureControl,
ScaleControl,
)
# Add all plugins with default settings to keep it simple but powerful
MapSearch().add_to(m)
LayerControl().add_to(m)
HeatmapControl(agg="sum").add_to(m)
ScaleControl().add_to(m)
MeasureControl().add_to(m)
Fullscreen().add_to(m)
print("๐ foliplus engine active: Ready for exploration.")
๐ foliplus engine active: Ready for exploration.
4. Display Map#
Run the next cell to render the interactive map in Notebook.
If you want to share the result, use the optional HTML export section below.
m
If you want to view the map in a browser or host it as a static file, export it to HTML.
file = "map.html"
m.save(file)
print(f"โ
Saved: {file}")
โ
Saved: map.html
5. Troubleshooting & Tips#
Map Blank or Not Rendering: Ensure the notebook is trusted and that the map display cell (Cell 7) was the last one executed.
Dependency Issues: If
dtoolkitorgeopandasare missing, install them via the suggested command in Section 1 and restart the kernel.Custom Localization: While plugins auto-detect your browser language, you can force a locale globally:
LayerControl(locale="en").
6. Next Steps#
API Exploration: Refer to the API Reference for a deep dive into available properties.
Dynamic Theming: Experiment with
HeatmapControlcolor scales like"Viridis"or"Plasma".Real-World Integration: Swap the simulated data for your own local datasets to start generating professional spatial insights immediately.
Happy Mapping! You are now ready to build scalable, interactive maps with foliplus.