LgLeafletMap
LgLeafletMap displays a Leaflet map in a Lagoon application. The Blazor component renders only the container; all interactions with the map, layers, markers, drawings, geolocation, search controls, and routing pass through the LeafletMap object provided to the Map parameter.
<LgLeafletMap Map="@_map" CssClass="leaflet-map" />
- Namespace :
Lagoon.UI.Leaflet.Components - Inherits from :
LgComponentBase - NuGet package :
Lagoon.UI.Leaflet
LgLeafletMap is not in the main Lagoon.UI package. Add the Lagoon.UI.Leaflet module to the client project, then reference the initialization script:
<script src="_content/Lagoon.UI.Leaflet/js/app-init.js"></script>
This script loads the embedded Leaflet resources: Leaflet, Leaflet Draw, Geocoder, Routing Machine, Overpass Layer, and MarkerCluster, along with their stylesheets.
The component occupies 100% of its container. The class passed via CssClass must therefore define at least a height.
Demonstration
Try this component in the Lagoon showcase.
Installation / integration
- Add a reference to the
Lagoon.UI.Leafletpackage or project to the client application. - Add the script
_content/Lagoon.UI.Leaflet/js/app-init.jsto the application's host page. - Import the namespaces used by the map:
Lagoon.UI.Leaflet.ComponentsLagoon.UI.Leaflet.Components.Models
- If tiles, routing, or Overpass call external services, authorize their domains in the application's CSP.
Example for OpenStreetMap tiles:
{
"CSP": {
"img-src-add": "https://a.tile.openstreetmap.org"
}
}
OpenStreetMap, OSRM, MapBox, and Overpass tile URLs are external services: they do not constitute a Lagoon application endpoint.
Usage
Simple map with tiles and markers
@inherits LgPage
@using Lagoon.UI.Leaflet.Components
@using Lagoon.UI.Leaflet.Components.Models
<LgLeafletMap Map="@_map" CssClass="leaflet-map" />
<LgButton Text="#LeafletPanToParis" OnClick="PanToParis" />
<LgButton Text="#LeafletLocateMe" OnClick="LocateUser" />
<style>
.leaflet-map {
height: 600px;
}
</style>
using System.Drawing;
using Lagoon.UI.Leaflet.Components;
using Lagoon.UI.Leaflet.Components.Models;
public partial class LeafletDemoPage : LgPage
{
// Instance driven by the component; it centralizes layers and Leaflet JS calls.
private LeafletMap _map;
// Initial coordinates displayed on first map render.
private readonly LatLng _initialCenter = new(46.227638f, 2.213749f);
protected override void OnInitialized()
{
_map = new LeafletMap(JS)
{
Center = _initialCenter,
Zoom = 5,
MinZoom = 3,
MaxZoom = 18,
};
// Wait for Leaflet to be created on the JavaScript side before adding layers.
_map.OnInitialized += InitializeMapLayers;
}
// Add tiles and markers after actual map initialization.
private void InitializeMapLayers()
{
TileLayer openStreetMap = new()
{
UrlTemplate = "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
Attribution = "© OpenStreetMap contributors",
};
_map.AddLayer(openStreetMap);
_map.AddBaseLayer(openStreetMap.Id, "OpenStreetMap");
Marker marker = new(new PointF(48.8566f, 2.3522f))
{
Tooltip = new Tooltip { Content = "#LeafletParisTooltip" },
Popup = new Popup { Content = "#LeafletParisPopup" },
};
_map.AddLayer(marker);
}
// Move the view to Paris with Leaflet animation.
private void PanToParis()
{
_map.PanTo(new PointF(48.8566f, 2.3522f), animate: true, duration: 1.5f);
}
// Request browser position; the result arrives in the OnLocationFound event.
private void LocateUser()
{
_map.Locate(setView: true, maxZoom: 16);
}
}
Drawing and GeoJSON
AddDrawControl() adds the Leaflet Draw toolbar. Drawings created, modified, or deleted are raised by OnDrawCreated, OnDrawEdited, and OnDrawDeleted. ToGeoJSON(string layerId) serializes an existing layer.
using Lagoon.UI.Leaflet.Components;
using Lagoon.UI.Leaflet.Components.Models;
public partial class LeafletDrawPage : LgPage
{
// Map used to enable drawing and retrieve layers produced by the user.
private LeafletMap _map;
// Last GeoJSON extracted from a drawn layer.
private string _lastGeoJson;
protected override void OnInitialized()
{
_map = new LeafletMap(JS)
{
Center = new LatLng(46.227638f, 2.213749f),
Zoom = 5,
};
// Drawing controls and events are available only after the first Leaflet render.
_map.OnInitialized += InitializeDrawTools;
}
// Enable Leaflet Draw and subscribe to creation, modification, and deletion events.
private void InitializeDrawTools()
{
_map.AddDrawControl();
_map.OnDrawCreated += OnDrawCreated;
_map.OnDrawEdited += OnDrawEdited;
_map.OnDrawDeleted += OnDrawDeleted;
}
// Keep the new layer and immediately extract its GeoJSON representation.
private void OnDrawCreated(LeafletMap sender, Layer createdLayer)
{
_lastGeoJson = sender.ToGeoJSON(createdLayer.Id);
}
// Iterate through modified layers to retrieve the latest GeoJSON state.
private void OnDrawEdited(LeafletMap sender, List<Layer> editedLayers)
{
if (editedLayers.Count > 0)
{
_lastGeoJson = sender.ToGeoJSON(editedLayers[0].Id);
}
}
// Clean up local state when drawn layers are deleted.
private void OnDrawDeleted(LeafletMap sender, List<Layer> deletedLayers)
{
_lastGeoJson = null;
}
}
Search, routing, and Overpass
AddSearchControl()adds the address search control.AddOsrmRoutingControl(RoutingControlOptions)adds routing via OSRM.AddMapBoxRoutingControl(string accessToken, RoutingControlOptions)adds MapBox routing.AddOverPassLayer(string query, string endPoint = "https://overpass-api.de/api/")adds the result of an Overpass QL query.GetDataFromOverpassAPIAsync(string query)returns the Overpass result in JSON format.
using Lagoon.UI.Leaflet.Components.Models;
public partial class LeafletRoutingPage : LgPage
{
// Map initialized elsewhere on the page; the methods below add external controls.
private LeafletMap _map;
// Add OSRM routing calculation between Rennes and Nantes.
private void AddOsrmRoutingControl()
{
_map.AddOsrmRoutingControl(new RoutingControlOptions
{
Collapsible = true,
Waypoints = new[]
{
new LatLng(48.117266f, -1.6777926f),
new LatLng(47.218371f, -1.553621f),
},
Router = new Router
{
ServiceUrl = "https://router.project-osrm.org/route/v1",
Profile = "driving",
},
});
}
// Add hospitals near Aix-en-Provence from Overpass.
private void AddHospitalsLayer()
{
_map.AddOverPassLayer("[out:json][timeout:25];nwr(around:10000,43.529742,5.447427)[\"amenity\"=\"hospital\"];out center;");
}
}
Marker clusters
MarkerClusterGroup is a Leaflet layer managed by the same component. It groups Markers, can receive markers dynamically, and exposes cluster events.
using System.Drawing;
using Lagoon.UI.Leaflet.Components.Models;
public partial class LeafletClusterPage : LgPage
{
// Cluster group kept to add or remove markers after rendering.
private MarkerClusterGroup _clusterGroup;
// Add the cluster group to the map after Leaflet initialization.
private void AddClusterGroup(LeafletMap map)
{
_clusterGroup = new MarkerClusterGroup
{
Options = new MarkerClusterOptions
{
IncludeClusterBoundsInEvents = true,
IncludeTargetZoomInEvents = true,
IconPreset = ClusterIconPreset.SmallMediumLarge,
},
};
_clusterGroup.Markers.Add(new Marker(new PointF(48.8566f, 2.3522f))
{
Tooltip = new Tooltip { Content = "#LeafletParisTooltip" },
});
_clusterGroup.OnClusterClick += OnClusterClick;
map.AddLayer(_clusterGroup);
}
// React to cluster click; ChildCount comes from the MarkerCluster plugin.
private void OnClusterClick(MarkerClusterGroup sender, MarkerClusterGroup.ClusterEventArgs e)
{
ShowInformation("#LeafletClusterClicked");
}
// Add a marker to the group already attached to the map.
private void AddMarkerToCluster()
{
Marker marker = new(new PointF(45.7640f, 4.8357f))
{
Tooltip = new Tooltip { Content = "#LeafletLyonTooltip" },
};
_clusterGroup.AddMarker(JS, marker);
}
}
Component API
| Property | Type | Default | Description |
|---|---|---|---|
CssClass | string | null | CSS class added to the component's outer container. |
Map | LeafletMap | null | Instance used to create the map and drive Leaflet. |
No events are exposed directly by LgLeafletMap. Events are carried by LeafletMap and the layers.
LeafletMap object
Properties
| Property | Type | Default | Description |
|---|---|---|---|
Center | LatLng | new LatLng() | Initial geographic center. |
Zoom | float | 0 | Initial zoom level. |
MinZoom | float? | null | Minimum allowed zoom. |
MaxZoom | float? | null | Maximum allowed zoom. |
MaxBounds | LatLngBound | null | Geographic navigation limits. |
ZoomControl | bool | true | Whether the Leaflet zoom control is added. |
Id | string | generated | Technical identifier used by JavaScript interoperability. |
Main methods
| Method | Description |
|---|---|
AddLayer(Layer layer) | Add a layer to the map after initialization. |
RemoveLayer(Layer layer) | Remove an existing layer. |
GetLayers() | Return the layers currently known on the .NET side. |
FitBounds(PointF corner1, PointF corner2, PointF? padding = null, float? maxZoom = null) | Adjust the view to contain two geographic corners. |
PanTo(PointF position, bool animate = false, float duration = 0.25f, float easeLinearity = 0.25f, bool noMoveStart = false) | Move the map center. |
GetCenter() | Read the current center from Leaflet. |
GetZoom() | Read the current zoom from Leaflet. |
ZoomIn(MouseEventArgs e) | Increase zoom. |
ZoomOutAsync(MouseEventArgs e) | Decrease zoom. |
Locate(...) | Start browser geolocation. |
StopLocate() | Stop geolocation in follow mode. |
AddDrawControl() | Add the drawing toolbar. |
AddSearchControl() | Add the search control. |
AddOsrmRoutingControl(RoutingControlOptions routingControlOptions) | Add an OSRM routing control. |
AddMapBoxRoutingControl(string accessToken, RoutingControlOptions routingControlOptions) | Add a MapBox routing control. |
ToGeoJSON(string layerId) | Return the GeoJSON representation of a layer. |
SetMaxBounds(LatLngBound bounds) | Set navigation limits. |
AddBaseLayer(string layerId, string name) | Add a base layer to the layer selector. |
AddOverlay(string layerId, string name) | Add an overlay to the layer selector. |
AddOverPassLayer(string query, string endPoint = "https://overpass-api.de/api/") | Add a layer from an Overpass QL query. |
GetDataFromOverpassAPIAsync(string query) | Call Overpass and return raw JSON. |
Map events
| Event | Type | Description |
|---|---|---|
OnInitialized | Action | Raised after the first render and map creation on the JavaScript side. |
OnZoomLevelsChange | MapEventHandler | Raised when zoom levels change. |
OnResize | MapResizeEventHandler | Raised when the map is resized. |
OnUnload | MapEventHandler | Raised when the map is unloaded. |
OnViewReset | MapEventHandler | Raised when the view is reset. |
OnLoad | MapEventHandler | Raised when the map loads. |
OnZoomStart | MapEventHandler | Raised at the start of a zoom. |
OnMoveStart | MapEventHandler | Raised at the start of a move. |
OnZoom | MapEventHandler | Raised during a zoom. |
OnMove | MapEventHandler | Raised during a move. |
OnZoomEnd | MapEventHandler | Raised at the end of a zoom. |
OnMoveEnd | MapEventHandler | Raised at the end of a move. |
OnMouseMove | MouseEventHandler | Raised when the mouse moves over the map. |
OnKeyPress | MapEventHandler | Raised when a key producing a character is pressed. |
OnKeyDown | MapEventHandler | Raised when a key is pressed down. |
OnKeyUp | MapEventHandler | Raised when a key is released. |
OnPreClick | MouseEventHandler | Raised before Leaflet click. |
OnClick | MouseEventHandler | Raised on a map click. |
OnDblClick | MouseEventHandler | Raised on a double-click. |
OnMouseDown | MouseEventHandler | Raised on mouse button press. |
OnMouseUp | MouseEventHandler | Raised on mouse button release. |
OnMouseOver | MouseEventHandler | Raised when the mouse enters the map. |
OnMouseOut | MouseEventHandler | Raised when the mouse leaves the map. |
OnContextMenu | MouseEventHandler | Raised on Leaflet context menu. |
OnLocationFound | LocationEventHandler | Raised when geolocation succeeds. |
OnDrawCreated | DrawCreatedEventHandler | Raised when a layer is drawn. |
OnDrawEdited | DrawEditedEventHandler | Raised when one or more layers are modified. |
OnDrawDeleted | DrawDeletedEventHandler | Raised when one or more layers are deleted. |
Supported layers
AddLayer accepts the following types:
| Layer | Usage |
|---|---|
TileLayer | Raster tiles via UrlTemplate, attribution, and zoom bounds. |
MbTilesLayer | MBTiles tiles. |
ShapefileLayer | Shapefile data. |
Marker | Point marker with icon, popup, and tooltip. |
Rectangle | Vector rectangle. |
Circle | Vector circle with center and radius. |
Polygon | Vector polygon. |
Polyline | Vector line. |
ImageLayer | Georeferenced image. |
GeoJsonDataLayer | Layer created from a GeoJSON string. |
MarkerClusterGroup | Clustered marker group. |
Layers inherit from Layer, which provides Id, Pane, Attribution, Tooltip, Popup, and events OnAdd, OnRemove, OnPopupOpen, OnPopupClose, OnTooltipOpen, OnTooltipClose. Interactive layers also inherit from InteractiveLayer, which provides IsInteractive, IsBubblingMouseEvents, and standard mouse events.
Routing options
| Property | Type | Default | Description |
|---|---|---|---|
RoutingControlOptions.Waypoints | LatLng[] | null | Initial waypoints. |
RoutingControlOptions.Router | Router | new Router() | Router used to calculate routes. |
RoutingControlOptions.Collapsible | bool? | null | Whether to display the control collapse button. |
RoutingControlOptions.ShowAlternatives | bool | false | Show alternative routes when they exist. |
Router.ServiceUrl | string | https://router.project-osrm.org/route/v1 | Routing service URL. |
Router.Timeout | float | 30000 | Maximum route calculation timeout in milliseconds. |
Router.Profile | string | driving | OSRM profile used. |
Router.PolylinePrecision | float | 5 | Polyline decoding precision. |
Router.UseHints | bool | false | Whether hints are sent to the service. |
Clusters
Options
| Property | Type | Default | Description |
|---|---|---|---|
ShowCoverageOnHover | bool | true | Show coverage polygon on hover. |
ZoomToBoundsOnClick | bool | true | Zoom to cluster bounds on click. |
SpiderfyOnMaxZoom | bool | true | Expand cluster at maximum zoom. |
MaxClusterRadius | int? | null | Maximum cluster radius. |
MaxClusterRadiusFunction | string | null | Name of a global JavaScript function calculating the radius. |
IconCreateFunction | string | null | Name of a global JavaScript function creating the icon. |
IconPreset | ClusterIconPreset | None | Built-in icon preset. |
CustomIcons | List<ClusterIconRange> | null | Custom ranges for generating icons. |
PolygonOptions | ClusterPolygonOptions | null | Coverage polygon style. |
DisableClusteringAtZoom | int? | null | Zoom level from which markers are no longer grouped. |
SingleMarkerMode | bool? | null | Show isolated markers with a cluster icon. |
SpiderfyOnEveryZoom | bool? | null | Keep expanded state during zooms. |
SpiderfyDistanceMultiplier | double? | null | Multiply the spacing between expanded markers. |
RemoveOutsideVisibleBounds | bool? | null | Remove clusters outside the visible area for performance. |
Animate | bool? | null | Animate cluster transitions. |
AnimateAddingMarkers | bool? | null | Animate individual marker addition. |
ChunkedLoading | bool? | null | Enable progressive marker loading. |
ChunkInterval | int? | null | Chunk duration in milliseconds. |
ChunkDelay | int? | null | Pause between chunks in milliseconds. |
SpiderLegPolylineOptions | ClusterSpiderLegPolylineOptions | null | Spiderfy leg style. |
SpiderfyShapePositionsFunction | string | null | Name of a global JavaScript function for spiderfy position. |
IncludeClusterBoundsInEvents | bool | false | Add cluster bounds to event arguments. |
IncludeChildMarkerIdsInEvents | bool | false | Add child marker IDs to event arguments. |
IncludeTargetZoomInEvents | bool | false | Add target zoom to event arguments. |
Methods and events
| Member | Type | Description |
|---|---|---|
Markers | List<Marker> | Markers contained in the group. |
Options | MarkerClusterOptions | MarkerCluster plugin options. |
AddMarker(IJSInProcessRuntime jsRuntime, Marker marker) | method | Add a marker dynamically. |
RemoveMarker(IJSInProcessRuntime jsRuntime, string markerId) | method | Remove a marker dynamically. |
Clear(IJSInProcessRuntime jsRuntime) | method | Clear the group. |
OnChunkProgress | event | Raised during progressive loading. |
OnClusterClick | event | Raised on cluster click. |
OnClusterMouseOver | event | Raised when the mouse enters a cluster. |
OnClusterMouseOut | event | Raised when the mouse leaves a cluster. |
OnClusterAnimationEnd | event | Raised at the end of a cluster animation. |
OnClusterSpiderfied | event | Raised after a cluster is expanded. |
OnClusterUnspiderfied | event | Raised after a cluster is collapsed. |
Related enumerations
ClusterIconPreset
ClusterIconPreset is not decorated with [Flags].
| Value | Description |
|---|---|
None | No preset: the plugin's default behavior or IconCreateFunction is used. |
SmallMediumLarge | Standard style based on small, medium, and large thresholds. |
JavaScript interoperability
LgLeafletMap creates a .NET reference to the Map object on first render and calls window.leafletBlazor.create. The following actions then pass through LgLeafletInterops: map creation, adding or removing layers, zoom, panning, geolocation, drawing, search, routing, Overpass, and clusters. JavaScript callbacks invoke the [JSInvokable] methods of .NET objects to raise the events listed above.