Skip to main content

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
Separate module

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.

Required size

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​

  1. Add a reference to the Lagoon.UI.Leaflet package or project to the client application.
  2. Add the script _content/Lagoon.UI.Leaflet/js/app-init.js to the application's host page.
  3. Import the namespaces used by the map:
    • Lagoon.UI.Leaflet.Components
    • Lagoon.UI.Leaflet.Components.Models
  4. 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​

LeafletDemoPage.razor
@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>
LeafletDemoPage.razor.cs
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 = "&copy; 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.

LeafletDrawPage.razor.cs
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.
LeafletRoutingPage.razor.cs
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.

LeafletClusterPage.razor.cs
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​

PropertyTypeDefaultDescription
CssClassstringnullCSS class added to the component's outer container.
MapLeafletMapnullInstance 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​

PropertyTypeDefaultDescription
CenterLatLngnew LatLng()Initial geographic center.
Zoomfloat0Initial zoom level.
MinZoomfloat?nullMinimum allowed zoom.
MaxZoomfloat?nullMaximum allowed zoom.
MaxBoundsLatLngBoundnullGeographic navigation limits.
ZoomControlbooltrueWhether the Leaflet zoom control is added.
IdstringgeneratedTechnical identifier used by JavaScript interoperability.

Main methods​

MethodDescription
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​

EventTypeDescription
OnInitializedActionRaised after the first render and map creation on the JavaScript side.
OnZoomLevelsChangeMapEventHandlerRaised when zoom levels change.
OnResizeMapResizeEventHandlerRaised when the map is resized.
OnUnloadMapEventHandlerRaised when the map is unloaded.
OnViewResetMapEventHandlerRaised when the view is reset.
OnLoadMapEventHandlerRaised when the map loads.
OnZoomStartMapEventHandlerRaised at the start of a zoom.
OnMoveStartMapEventHandlerRaised at the start of a move.
OnZoomMapEventHandlerRaised during a zoom.
OnMoveMapEventHandlerRaised during a move.
OnZoomEndMapEventHandlerRaised at the end of a zoom.
OnMoveEndMapEventHandlerRaised at the end of a move.
OnMouseMoveMouseEventHandlerRaised when the mouse moves over the map.
OnKeyPressMapEventHandlerRaised when a key producing a character is pressed.
OnKeyDownMapEventHandlerRaised when a key is pressed down.
OnKeyUpMapEventHandlerRaised when a key is released.
OnPreClickMouseEventHandlerRaised before Leaflet click.
OnClickMouseEventHandlerRaised on a map click.
OnDblClickMouseEventHandlerRaised on a double-click.
OnMouseDownMouseEventHandlerRaised on mouse button press.
OnMouseUpMouseEventHandlerRaised on mouse button release.
OnMouseOverMouseEventHandlerRaised when the mouse enters the map.
OnMouseOutMouseEventHandlerRaised when the mouse leaves the map.
OnContextMenuMouseEventHandlerRaised on Leaflet context menu.
OnLocationFoundLocationEventHandlerRaised when geolocation succeeds.
OnDrawCreatedDrawCreatedEventHandlerRaised when a layer is drawn.
OnDrawEditedDrawEditedEventHandlerRaised when one or more layers are modified.
OnDrawDeletedDrawDeletedEventHandlerRaised when one or more layers are deleted.

Supported layers​

AddLayer accepts the following types:

LayerUsage
TileLayerRaster tiles via UrlTemplate, attribution, and zoom bounds.
MbTilesLayerMBTiles tiles.
ShapefileLayerShapefile data.
MarkerPoint marker with icon, popup, and tooltip.
RectangleVector rectangle.
CircleVector circle with center and radius.
PolygonVector polygon.
PolylineVector line.
ImageLayerGeoreferenced image.
GeoJsonDataLayerLayer created from a GeoJSON string.
MarkerClusterGroupClustered 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​

PropertyTypeDefaultDescription
RoutingControlOptions.WaypointsLatLng[]nullInitial waypoints.
RoutingControlOptions.RouterRouternew Router()Router used to calculate routes.
RoutingControlOptions.Collapsiblebool?nullWhether to display the control collapse button.
RoutingControlOptions.ShowAlternativesboolfalseShow alternative routes when they exist.
Router.ServiceUrlstringhttps://router.project-osrm.org/route/v1Routing service URL.
Router.Timeoutfloat30000Maximum route calculation timeout in milliseconds.
Router.ProfilestringdrivingOSRM profile used.
Router.PolylinePrecisionfloat5Polyline decoding precision.
Router.UseHintsboolfalseWhether hints are sent to the service.

Clusters​

Options​

PropertyTypeDefaultDescription
ShowCoverageOnHoverbooltrueShow coverage polygon on hover.
ZoomToBoundsOnClickbooltrueZoom to cluster bounds on click.
SpiderfyOnMaxZoombooltrueExpand cluster at maximum zoom.
MaxClusterRadiusint?nullMaximum cluster radius.
MaxClusterRadiusFunctionstringnullName of a global JavaScript function calculating the radius.
IconCreateFunctionstringnullName of a global JavaScript function creating the icon.
IconPresetClusterIconPresetNoneBuilt-in icon preset.
CustomIconsList<ClusterIconRange>nullCustom ranges for generating icons.
PolygonOptionsClusterPolygonOptionsnullCoverage polygon style.
DisableClusteringAtZoomint?nullZoom level from which markers are no longer grouped.
SingleMarkerModebool?nullShow isolated markers with a cluster icon.
SpiderfyOnEveryZoombool?nullKeep expanded state during zooms.
SpiderfyDistanceMultiplierdouble?nullMultiply the spacing between expanded markers.
RemoveOutsideVisibleBoundsbool?nullRemove clusters outside the visible area for performance.
Animatebool?nullAnimate cluster transitions.
AnimateAddingMarkersbool?nullAnimate individual marker addition.
ChunkedLoadingbool?nullEnable progressive marker loading.
ChunkIntervalint?nullChunk duration in milliseconds.
ChunkDelayint?nullPause between chunks in milliseconds.
SpiderLegPolylineOptionsClusterSpiderLegPolylineOptionsnullSpiderfy leg style.
SpiderfyShapePositionsFunctionstringnullName of a global JavaScript function for spiderfy position.
IncludeClusterBoundsInEventsboolfalseAdd cluster bounds to event arguments.
IncludeChildMarkerIdsInEventsboolfalseAdd child marker IDs to event arguments.
IncludeTargetZoomInEventsboolfalseAdd target zoom to event arguments.

Methods and events​

MemberTypeDescription
MarkersList<Marker>Markers contained in the group.
OptionsMarkerClusterOptionsMarkerCluster plugin options.
AddMarker(IJSInProcessRuntime jsRuntime, Marker marker)methodAdd a marker dynamically.
RemoveMarker(IJSInProcessRuntime jsRuntime, string markerId)methodRemove a marker dynamically.
Clear(IJSInProcessRuntime jsRuntime)methodClear the group.
OnChunkProgresseventRaised during progressive loading.
OnClusterClickeventRaised on cluster click.
OnClusterMouseOvereventRaised when the mouse enters a cluster.
OnClusterMouseOuteventRaised when the mouse leaves a cluster.
OnClusterAnimationEndeventRaised at the end of a cluster animation.
OnClusterSpiderfiedeventRaised after a cluster is expanded.
OnClusterUnspiderfiedeventRaised after a cluster is collapsed.

ClusterIconPreset​

ClusterIconPreset is not decorated with [Flags].

ValueDescription
NoneNo preset: the plugin's default behavior or IconCreateFunction is used.
SmallMediumLargeStandard 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.