# Map
**Also known as:** GeoMap, Maps
## Description
BitMap is a provider-pluggable interactive map. One API drives markers, vector shapes, GeoJSON and tile overlays across seven backends - Leaflet, MapLibre GL, Mapbox GL, OpenLayers, ArcGIS, Azure Maps and CesiumJS - and adds what they leave out, uniformly: two-way camera binding, marker clustering, Blazor-rendered popups, cooperative gestures, a keyboard and screen-reader story, loading states and theming that follows the app.
## Parameters
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| AnnounceViewChanges | `bool` | false | Announces the new centre and zoom through a polite live region after the user pans or zooms, throttled by ViewAnnouncementThrottle. |
| AutoResize | `bool` | true | Keeps the map sized to its container, which also recovers a map created inside a hidden tab. |
| Center | `BitMapLatLng?` | null | Two-way bindable centre: assigning it moves the map, panning writes it back. Unset, the provider's Center owns the camera. |
| ChildContent | `RenderFragment?` | null | Content floated above the map, such as custom controls. Only its children take the pointer, each sized to its content from the top-start corner. |
| Classes | `BitMapClassStyles?` | null | Custom CSS classes for different parts of the map. |
| Clustering | `BitMapClustering?` | null | Groups nearby markers into a bubble showing their count, the same way on every provider. Null draws every marker. |
| CooperativeGestures | `bool` | false | Requires ctrl/⌘ + wheel to zoom and two fingers to pan, so a bare gesture scrolls the page instead and shows a hint. |
| CooperativeGesturesTouchHint | `string` | Use two fingers to move the map | The hint shown when a one-finger drag is blocked. |
| CooperativeGesturesWheelHint | `string` | Use ctrl + scroll to zoom the map | The hint shown when a bare wheel gesture is blocked. |
| ErrorLabel | `string` | The map could not be loaded. | The text of the built-in failure message. |
| ErrorTemplate | `RenderFragment<Exception?>?` | null | Replaces the built-in failure message, receiving the exception when there is one. |
| EscapeToExit | `bool` | true | Moves the focus out of the canvas on Escape, so a focused map is never a keyboard trap. An open marker popup is closed first. |
| KeyboardInstructions | `string` | Use the arrow keys to pan the map, plus and minus to zoom, and Escape to leave the map. | The keyboard model, read by assistive technologies and shown while the canvas has keyboard focus. |
| LazyLoad | `bool` | false | Defers creating the map until its container is near the viewport. LoadState stays Idle until then. |
| LazyLoadRootMargin | `string` | 200px | How far outside the viewport the container still counts as visible for LazyLoad. |
| LoadingLabel | `string` | Loading map… | The text of the built-in loading indicator. |
| LoadingTemplate | `RenderFragment?` | null | Replaces the built-in loading indicator. |
| MarkerListActionHeader | `string` | Show on map | The label of the button bringing a marker into view, also the hidden column heading. |
| MarkerListCaption | `string` | Map markers | The caption of the marker table. Say what the markers are. |
| MarkerListLatitudeHeader | `string` | Latitude | The heading of the latitude column. |
| MarkerListLongitudeHeader | `string` | Longitude | The heading of the longitude column. |
| MarkerListMode | `BitMapMarkerListMode` | BitMapMarkerListMode.None | Renders the markers as a table of names and coordinates whose rows bring their marker into view - the text alternative a screen reader needs. |
| MarkerListNameHeader | `string` | Name | The heading of the name column. |
| MarkerListTemplate | `RenderFragment<IReadOnlyList<BitMapMarker>>?` | null | Replaces the built-in marker table. |
| MarkerListZoom | `double?` | 15 | The zoom a marker-list row brings its marker into view at. Null keeps the current zoom. |
| MarkerPopupTemplate | `RenderFragment<BitMapMarker>?` | null | The content of the popup a marker click opens, as live Blazor markup - escaped, and able to hold components and handlers. |
| Markers | `IEnumerable<BitMapMarker>?` | null | The markers as a collection. They compare by value, so only the changed ones are sent. It owns the set: imperative additions are reconciled away on its next change. |
| OnClick | `EventCallback<BitMapLatLng>` | | Fires when the map is clicked away from a marker or a vector layer. |
| OnClusterClick | `EventCallback<BitMapClusterClickArgs>` | | Fires when a cluster bubble is clicked, instead of OnMarkerClick. |
| OnContextMenu | `EventCallback<BitMapLatLng>` | | Fires on a right-click or a long press, with the coordinate under the pointer. |
| OnDoubleClick | `EventCallback<BitMapLatLng>` | | Fires when the map is double-clicked. |
| OnFullscreenChanged | `EventCallback<bool>` | | Fires when the map enters or leaves fullscreen, however it did. |
| OnGeoJsonFeatureClick | `EventCallback<BitMapGeoJsonFeatureClickArgs>` | | Fires when a feature of a GeoJSON layer is clicked, with its properties. |
| OnInteropError | `EventCallback<BitMapInteropErrorArgs>` | | Fires when a call into the provider fails. The component swallows these failures, so this is where to log them. |
| OnLoadStateChanged | `EventCallback<BitMapLoadState>` | | Fires whenever LoadState changes. |
| OnMarkerClick | `EventCallback<string>` | | Fires when a marker is clicked, with its id. |
| OnMarkerDragEnd | `EventCallback<BitMapMarkerDragEndArgs>` | | Fires when a draggable marker is dropped. |
| OnPopupClosed | `EventCallback` | | Fires when the MarkerPopupTemplate popup closes. |
| OnPopupOpened | `EventCallback<BitMapMarker>` | | Fires when the MarkerPopupTemplate popup opens, with its marker. |
| OnReady | `EventCallback` | | Fires once the map can take imperative calls, and again after a swap to a provider with another backend. A call made before it does nothing; only GetView throws. |
| OnRenderContextLost | `EventCallback` | | Fires when the browser drops the WebGL context the map renders into. |
| OnRenderContextRestored | `EventCallback` | | Fires when a lost WebGL context is restored. |
| OnVectorClick | `EventCallback<BitMapVectorClickArgs>` | | Fires when a vector layer is clicked. |
| OnViewChanged | `EventCallback<BitMapViewState>` | | Fires once a pan or zoom settles. |
| PopupAutoPan | `bool` | true | Pans the map as the MarkerPopupTemplate popup opens, just enough to bring the whole popup into view. |
| PopupCloseLabel | `string` | Close | The accessible name of the popup's close button. |
| PopupLabel | `string` | Marker details | The accessible name of the popup when its marker has neither an Alt nor a Title. |
| Provider | `TMapProvider?` | null | The provider's configuration: centre, zoom, tiles, tokens and interaction toggles. Compared by reference - assign a new instance to apply changes. |
| ReplayStateOnProviderSwap | `bool` | false | Replays the imperatively added markers, layers and overlays after a swap to a provider with another backend. |
| RespectReducedMotion | `bool` | true | Makes every camera move - FlyTo, SetView, FitBounds, a cluster's zoom, the keyboard - jump under a reduced-motion preference, unless the move is essential or ForceAnimation is set. |
| RoleDescription | `string` | interactive map | What a screen reader calls the map canvas in place of "region". The canvas is named by AriaLabel. |
| ShowLoading | `bool` | true | Shows the built-in loading indicator while the map is being created. |
| Styles | `BitMapClassStyles?` | null | Custom CSS styles for different parts of the map. |
| TMapProvider | `generic type` | | The provider type: BitLeafletMapProvider, BitMapLibreMapProvider, BitMapboxMapProvider, BitOpenLayersMapProvider, BitArcGisMapProvider, BitAzureMapsMapProvider or BitCesiumMapProvider. |
| UnsupportedLabel | `string` | This browser cannot display the map (WebGL is unavailable). | The text of the built-in unsupported-browser message. |
| UnsupportedTemplate | `RenderFragment?` | null | Replaces the built-in unsupported-browser message. |
| ViewAnnouncementFormatter | `Func<BitMapViewState, string>?` | null | Builds the announced text - a place name beats a pair of coordinates. |
| ViewAnnouncementThrottle | `TimeSpan` | 2 seconds | The minimum interval between two view announcements. |
| Zoom | `double?` | null | Two-way bindable zoom level: assigning it zooms the map, zooming writes it back. |
| AriaLabel | `string?` | null | Gets or sets the accessible label for the component, used by assistive technologies. |
| Class | `string?` | null | Gets or sets the CSS class name(s) to apply to the rendered element. |
| Dir | `BitDir?` | null | Gets or sets the text directionality for the component's content. |
| Disabled | `bool` | false | Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction. |
| ForceAnimation | `bool` | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. |
| HtmlAttributes | `Dictionary<string, object>` | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. An attribute written on the component wins over an entry of the same name. |
| Id | `string?` | null | Gets or sets the unique identifier for the component's root element. |
| Style | `string?` | null | Gets or sets the CSS style string to apply to the rendered element. |
| TabIndex | `string?` | null | Gets or sets the tab order index for the component when navigating with the keyboard. |
| Visibility | `BitVisibility` | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. |
## Public Members
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| IsReady | `bool` | false | True after the map is ready for interop calls. Until then the imperative methods do nothing. |
| LoadState | `BitMapLoadState` | BitMapLoadState.Idle | Where the map is in its lifecycle: Idle, Loading, Ready, Failed, or Unsupported. |
| LoadError | `Exception?` | null | The exception behind a Failed LoadState, when one was captured. |
| MarkerIds | `IReadOnlyCollection<string>` | | Ids of the markers currently on the map, in no guaranteed order. Read from the component's own snapshot, so it costs no interop round-trip. |
| OpenPopupMarker | `BitMapMarker?` | null | The marker whose MarkerPopupTemplate popup is open, or null when none is. |
| OpenPopup | `Func<string, ValueTask>` | | Opens the MarkerPopupTemplate popup for a marker. Does nothing when no template is set - use OpenMarkerPopup for the provider's own popup. |
| ClosePopup | `Func<bool, ValueTask>` | | Closes the MarkerPopupTemplate popup, if one is open. Pass true to return the focus to the map. |
| OrderedMarkers | `IReadOnlyList<BitMapMarker>` | | The markers currently on the map, in no guaranteed order. Costs no interop round-trip. |
| LayerIds | `IReadOnlyCollection<string>` | | Ids of the vector layers currently on the map, in no guaranteed order. Costs no interop round-trip. |
| TileOverlayIds | `IReadOnlyCollection<string>` | | Ids of the tile overlays currently on the map, in no guaranteed order. Costs no interop round-trip. |
| GetView | `Func<ValueTask<BitMapViewState>>` | | Returns a snapshot of the current viewport. Throws an InvalidOperationException before the map is ready. |
| SetView | `Func<BitMapLatLng, double?, bool, bool, ValueTask>` | | Pan and optionally zoom to the given center (center, zoom, animate, essential). Animation is skipped under a reduced-motion preference unless the move is marked essential. |
| FlyTo | `Func<BitMapLatLng, double?, bool, ValueTask>` | | Animated pan/zoom to the given center (center, zoom, essential). Becomes an instant jump under a reduced-motion preference unless marked essential. |
| SetZoom | `Func<double, bool, bool, ValueTask>` | | Set an absolute zoom level, keeping the current centre. |
| ZoomIn | `Func<double, bool, bool, ValueTask>` | | Zoom in by a number of levels (default 1) around the current centre. |
| ZoomOut | `Func<double, bool, bool, ValueTask>` | | Zoom out by a number of levels (default 1) around the current centre. |
| ZoomBy | `Func<double, bool, bool, ValueTask>` | | Change the zoom by a relative number of levels. Negative values zoom out. |
| PanBy | `Func<double, double, bool, bool, ValueTask>` | | Pan by a pixel offset. This is what pan buttons are built from, and shipping those matters: WCAG 2.2 SC 2.5.7 requires a single-pointer alternative to dragging the map. |
| Locate | `Func<BitMapGeolocationOptions?, ValueTask<BitMapGeolocationResult?>>` | | Asks the browser for the visitor's position and, unless turned off, pans there. Returns null when the browser denies the permission prompt or times out. |
| PanTo | `Func<BitMapLatLng, bool, bool, ValueTask>` | | Move the centre while keeping the current zoom. |
| Project | `Func<BitMapLatLng, ValueTask<BitMapPoint?>>` | | Where a coordinate currently sits inside the map container, in CSS pixels from its top-left corner. Null when it is not on screen. Only valid for the viewport it was read at. |
| FitBounds | `Func<BitMapLatLngBounds, int, double, bool, bool, ValueTask>` | | Fit the view to the given bounding box (bounds, padding, maxZoom, animate, essential); the maxZoom ceiling (default 18) keeps a box around a single place from dropping to street level. |
| FitBoundsToMarkers | `Func<int, double, bool, bool, ValueTask>` | | Fit the view to include every marker currently drawn, with the same arguments as FitBounds. |
| InvalidateSize | `Func<ValueTask>` | | Recalculate map size after a container resize. |
| AddMarker | `Func<BitMapMarker, ValueTask>` | | Add a marker to the map. |
| RemoveMarker | `Func<string, ValueTask>` | | Remove a marker by id. |
| ClearMarkers | `Func<ValueTask>` | | Remove all markers. |
| SetMarkerPosition | `Func<string, BitMapLatLng, ValueTask>` | | Move a marker to a new position. |
| OpenMarkerPopup | `Func<string, ValueTask>` | | Open a marker's popup. |
| CloseMarkerPopup | `Func<ValueTask<bool>>` | | Close the provider's open marker popup; true when one was open. ClosePopup closes the MarkerPopupTemplate one. |
| SyncMarkers | `Func<IEnumerable<BitMapMarker>, ValueTask>` | | Replace all markers in one batch. |
| AddPolyline | `Func<string, IReadOnlyList<BitMapLatLng>, BitMapVectorPathStyle?, ValueTask>` | | Add a polyline. |
| AddPolygon | `Func<string, IReadOnlyList<BitMapLatLng>, BitMapVectorPathStyle?, ValueTask>` | | Add a polygon. |
| AddCircle | `Func<string, BitMapLatLng, double, BitMapVectorPathStyle?, ValueTask>` | | Add a circle (radius in meters). |
| AddRectangle | `Func<string, BitMapLatLngBounds, BitMapVectorPathStyle?, ValueTask>` | | Add a rectangle. |
| AddGeoJson | `Func<string, string, BitMapVectorPathStyle?, ValueTask>` | | Add a GeoJSON layer. |
| RemoveLayer | `Func<string, ValueTask>` | | Remove a vector layer by id. |
| ClearVectorLayers | `Func<ValueTask>` | | Remove all vector layers. |
| AddTileOverlay | `Func<BitMapTileOverlay, ValueTask>` | | Add a tile overlay above the base map. |
| IsFullscreen | `bool` | false | Whether the map is currently displayed fullscreen. |
| RequestFullscreen | `Func<ValueTask<bool>>` | | Takes the map's container fullscreen - not the page - so overlay content and custom controls go with it. Call it from a user gesture: browsers only honour the request inside the short activation window a click opens. Returns whether the browser granted it. |
| ExitFullscreen | `Func<ValueTask<bool>>` | | Leaves fullscreen, if this map is the element currently displayed fullscreen. |
| ToggleFullscreen | `Func<ValueTask<bool>>` | | Enters fullscreen, or leaves it if the map is already fullscreen. |
| SetLayerVisible | `Func<string, bool, ValueTask>` | | Shows or hides a vector layer while keeping its definition. Unlike a zero opacity, a hidden layer stops hit-testing rather than swallowing clicks meant for what is underneath it. |
| IsLayerVisible | `Func<string, bool>` | | Whether a vector layer is currently drawn. Unknown ids report false. |
| SetLayerStyle | `Func<string, BitMapVectorPathStyle?, ValueTask>` | | Restyles an existing vector layer, keeping its geometry. A hidden layer keeps the new style for when it is shown again. |
| SetTileOverlayVisible | `Func<string, bool, ValueTask>` | | Shows or hides a tile overlay while keeping its definition. |
| IsTileOverlayVisible | `Func<string, bool>` | | Whether a tile overlay is currently drawn. Unknown ids report false. |
| SetTileOverlayOpacity | `Func<string, double, ValueTask>` | | Changes a tile overlay's opacity, which is how a raster overlay is blended against the basemap underneath it. |
| ClearTileOverlays | `Func<ValueTask>` | | Remove every tile overlay, leaving the base map alone. |
| RemoveTileOverlay | `Func<string, ValueTask>` | | Remove a tile overlay by id. |
| UniqueId | `Guid` | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. |
| RootElement | `ElementReference` | | Gets the reference to the root HTML element associated with this component. |
## Enums
### BitMapMarkerListMode Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| None | 0 | No list is rendered. |
| ScreenReaderOnly | 1 | The list is hidden visually but reachable by assistive technologies, and printed. |
| Visible | 2 | The list is rendered below the map for everyone. |
### BitMapLoadState Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Idle | 0 | Not started yet: prerendering, or waiting to scroll into view under LazyLoad. |
| Loading | 1 | The provider's assets are loading or the map is being created. |
| Ready | 2 | The map is live and every method can be called. |
| Failed | 3 | Creating the map failed; LoadError holds the exception. |
| Unsupported | 4 | The browser cannot run this provider - no WebGL for a GL-backed one. |
### BitPlacement Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Top | 0 | The top edge. |
| Bottom | 1 | The bottom edge. |
| Start | 2 | The edge the reading direction starts from - the left in LTR, the right in RTL. On the vertical axis, which does not turn around, it is the top. |
| End | 3 | The edge the reading direction ends at - the right in LTR, the left in RTL. On the vertical axis, which does not turn around, it is the bottom. |
| Left | 4 | The left edge, in both reading directions. |
| Right | 5 | The right edge, in both reading directions. |
| Center | 6 | The middle of the axis, against neither edge. |
| TopAndBottom | 7 | Both edges of the block axis at once. |
| StartAndEnd | 8 | Both edges of the inline axis at once, following the reading direction the way Start and End do. |
### BitVisibility Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Visible | 0 | The content of the component is visible. |
| Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). |
| Collapsed | 2 | The component is hidden (display:none). |
### BitDir Enum
| Name | Value | Description |
| :--- | :--- | :---------- |
| Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). |
| Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). |
| Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. |
## Sub Classes
### BitMapClassStyles Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Root | `string?` | null | Custom CSS classes/styles for the root element of the BitMap. |
| Canvas | `string?` | null | Custom CSS classes/styles for the focusable canvas the provider draws the map into. |
| Overlay | `string?` | null | Custom CSS classes/styles for the layer holding the ChildContent above the map. |
| Instructions | `string?` | null | Custom CSS classes/styles for the keyboard instructions shown while the canvas has keyboard focus. |
| GestureHint | `string?` | null | Custom CSS classes/styles for the hint shown while a gesture is blocked by the cooperative gestures. |
| Status | `string?` | null | Custom CSS classes/styles for the cover shown while the map is loading, has failed, or is unsupported. |
| Spinner | `string?` | null | Custom CSS classes/styles for the spinner of the built-in loading indicator. |
| Popup | `string?` | null | Custom CSS classes/styles for the popup the MarkerPopupTemplate is rendered in. |
| PopupCloseButton | `string?` | null | Custom CSS classes/styles for the close button of the popup. |
| PopupBody | `string?` | null | Custom CSS classes/styles for the body of the popup, holding the MarkerPopupTemplate content. |
| MarkerList | `string?` | null | Custom CSS classes/styles for the container of the marker list rendered next to the map. |
| MarkerListButton | `string?` | null | Custom CSS classes/styles for each "Show on map" button of the built-in marker table. |
### BitMapMarker Properties
A record, compared by value. Each property is honoured by every provider unless it says otherwise.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Id | `string` | | Unique identifier of the marker within the map. Required. |
| Position | `BitMapLatLng` | | The coordinate of the marker. Required. |
| Alt | `string?` | null | The accessible name of the marker, and its name in the marker table. |
| Title | `string?` | null | The native tooltip of the marker, and its accessible name when Alt is not set. |
| PopupText | `string?` | null | Plain text shown in the provider's popup on click. Escaped - safe for user data. |
| PopupHtml | `MarkupString?` | null | Raw HTML shown in the provider's popup on click. Not escaped - never pass user data. |
| TooltipText | `string?` | null | Plain text shown on hover and on keyboard focus (not on ArcGIS and Cesium). |
| TooltipHtml | `MarkupString?` | null | Raw HTML shown on hover and on keyboard focus. Not escaped. |
| TooltipPermanent | `bool` | false | Keeps the tooltip open instead of only on hover and focus. |
| TooltipPlacement | `BitPlacement?` | null | Where the tooltip opens against the marker. Only Top, Bottom, Left, Right and Center are honoured; any other value, or none, leaves the provider to choose. |
| Focusable | `bool` | true | Makes the marker a tab stop that Enter or Space opens. Turn off for decorative pins. |
| Draggable | `bool` | false | Lets the user move the marker, reported by OnMarkerDragEnd. |
| Color | `string?` | null | The color of the default pin - any CSS color, a theme variable included. Null takes --bit-Map-marker-color. |
| IconUrl | `string?` | null | The image drawn instead of the default pin. |
| IconWidth | `int?` | null | The width of the icon in pixels. Null takes 25 for the pin, 32 for an IconUrl. |
| IconHeight | `int?` | null | The height of the icon in pixels. Null takes 41 for the pin, 32 for an IconUrl. |
| IconAnchorX | `int?` | null | The pixel of the icon, from its left, that sits on the coordinate. Null is the horizontal centre. |
| IconAnchorY | `int?` | null | The pixel of the icon, from its top, that sits on the coordinate. Null is the bottom edge. |
| Opacity | `double` | 1 | The opacity of the marker, 0 to 1. |
| RiseOnHover | `bool` | false | Brings the marker above the others under the pointer (Leaflet). |
| ZIndexOffset | `int` | 0 | Stacks the marker above or below the others (Leaflet). |
### BitMapClustering Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| RadiusPixels | `int` | 60 | How close, in screen pixels, markers have to be to join one bubble: a larger radius gives fewer, denser bubbles. |
| MaxZoom | `double` | 16 | The zoom at and above which every marker is drawn individually. |
| MinPoints | `int` | 2 | The fewest markers a bubble stands for. |
| Color | `string?` | null | The fill of the bubbles. Null takes --bit-Map-cluster-background, which falls back to the primary color. |
| TextColor | `string?` | null | The color of the count. Null takes --bit-Map-cluster-color, which falls back to the text color of the primary color. |
| CullOffscreen | `bool` | true | Keeps the markers outside the viewport off the map - most of the performance win. |
| MaxRenderedMarkers | `int` | 2000 | The most individual markers drawn at once past MaxZoom. |
| ExpandPaddingPixels | `int` | 48 | The padding of the zoom a bubble click makes to fit its markers. |
| AriaLabelFormat | `string` | Cluster of {0} markers | The accessible name of a bubble; {0} is its count. |
| ZoomOnClick | `bool` | true | Zooms to fit a bubble's markers on click. Turn off to handle OnClusterClick yourself. |
### BitMapVectorPathStyle Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Color | `string?` | null | The stroke color - any CSS color, a theme variable included. Null takes --bit-Map-vector-color. |
| Weight | `double` | 3 | The stroke width in pixels. |
| Opacity | `double` | 1 | The stroke opacity, 0 to 1. |
| Fill | `bool` | true | Whether a closed shape is filled. Unlike a zero FillOpacity, no fill also takes no clicks. |
| FillColor | `string?` | null | The fill color. Null takes Color. |
| FillOpacity | `double` | 0.2 | The fill opacity, 0 to 1. |
| DashArray | `string?` | null | The dash pattern of the stroke, such as "6 4". |
| DashOffset | `string?` | null | Where the dash pattern starts. |
| LineCap | `BitMapLineCap` | BitMapLineCap.Round | The shape of the stroke's ends: Round, Butt or Square. |
| LineJoin | `BitMapLineJoin` | BitMapLineJoin.Round | The shape of the stroke's corners: Round, Bevel or Miter. |
### BitMapTileOverlay Properties
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Id | `string` | | Unique identifier of the overlay within the map. Required. |
| UrlTemplate | `string` | | The XYZ template with {z}, {x}, {y} and optional {s} placeholders. Required. |
| Attribution | `string?` | null | The credit the tile source requires, shown in the attribution control. |
| Opacity | `double` | 1 | The opacity of the overlay, 0 to 1. |
| ZIndex | `int` | 100 | The stacking order of the overlay. |
| MinZoom | `int` | 0 | The lowest zoom the source publishes tiles for. |
| MaxZoom | `int` | 19 | The highest zoom the source publishes tiles for. |
| Subdomains | `string` | abc | The values {s} takes, for sources that shard their tiles across hostnames. |
### BitMapProviderBase Properties
What every provider shares. Each one adds its own options - tiles, style URLs, tokens - documented on its type.
| Name | Type | Default Value | Description |
| :--- | :--- | :------------ | :---------- |
| Center | `BitMapLatLng` | 51.505, -0.09 | The initial centre. |
| Zoom | `double` | 13 | The initial zoom. |
| MinZoom | `int?` | null | The lowest zoom the user can reach. |
| MaxZoom | `int?` | null | The highest zoom the user can reach. |
| ZoomControl | `bool` | true | Shows the provider's +/- buttons. |
| AttributionControl | `bool` | true | Shows the attribution - often a licence term of the tiles. |
| ScrollWheelZoom | `bool` | true | Zooms with the mouse wheel. |
| DoubleClickZoom | `bool` | true | Zooms on a double click. |
| BoxZoom | `bool` | true | Zooms to a shift-dragged box (Leaflet, OpenLayers, MapLibre, Mapbox). |
| Dragging | `bool` | true | Pans by dragging. |
| KeyboardNavigation | `bool` | true | Pans and zooms with the keyboard while the canvas has focus. |
| SuppressBrowserContextMenu | `bool` | false | Keeps the browser's own menu from opening on a right-click. Only with a menu of your own in its place. |
| MaxBounds | `BitMapLatLngBounds?` | null | Keeps the view inside a rectangle (Leaflet, MapLibre, Mapbox). |
| AdditionalOptions | `Dictionary<string, object?>` | | Passed straight to the library's map constructor (Leaflet, MapLibre, Mapbox). |
## CSS Variables
Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance to restyle it and every instance nested inside it, which inherits the value too - a parameter changes one alone, as does the real CSS property on its `Style` / `Styles` when that property does not inherit (`opacity`); an inherited one (`color`, `font-family`) reaches the nested instances that do not set it themselves.
| Name | Default Value | Description |
| :--- | :------------ | :---------- |
| `--bit-Map-height` | 100% | Height of the map. A percentage needs a container with a height of its own. |
| `--bit-Map-background` | --bit-clr-bg-sec | What shows where no tile is drawn: before the tiles load, behind the loading cover and around a fullscreen map. |
| `--bit-Map-tile-filter` | none | CSS filter on the raster tiles of Leaflet and OpenLayers - never the vectors and markers on them. invert(1) hue-rotate(180deg) is a dark basemap. |
| `--bit-Map-border` | none | Border of the map. |
| `--bit-Map-radius` | --bit-shp-radius-none | Corner radius of the map, which clips the tiles too. |
| `--bit-Map-focus-color` | --bit-clr-pri-focus | Focus outline of the map canvas. |
| `--bit-Map-disabled-opacity` | --bit-opa-dis | Opacity of the canvas of a disabled map. |
| `--bit-Map-popup-background` | --bit-clr-bg-pri | Background of the popups (the providers' included) and the keyboard instructions. |
| `--bit-Map-popup-color` | --bit-clr-fg-pri | Text color of the popups and the keyboard instructions. |
| `--bit-Map-popup-radius` | --bit-shp-radius-popup | Corner radius of the popups, the tooltips and the keyboard instructions. |
| `--bit-Map-popup-shadow` | --bit-shd-popup | Elevation of the popups and the keyboard instructions. |
| `--bit-Map-popup-padding` | spacing(1) spacing(1.25) | Padding of the MarkerPopupTemplate popup. |
| `--bit-Map-popup-max-width` | 18rem | Widest the MarkerPopupTemplate popup gets before wrapping. |
| `--bit-Map-tooltip-background` | --bit-clr-tooltip-bg | Background of the marker tooltips. |
| `--bit-Map-tooltip-color` | --bit-clr-tooltip-fg | Text color of the marker tooltips. |
| `--bit-Map-hint-background` | --bit-clr-bg-overlay | Backdrop of the cooperative-gestures hint. |
| `--bit-Map-hint-color` | --bit-clr-ntr-white | Text color of the cooperative-gestures hint. |
| `--bit-Map-marker-color` | --bit-clr-pri | The default pin, on every provider, unless BitMapMarker.Color is set. |
| `--bit-Map-vector-color` | --bit-clr-pri | Stroke and fill of the shapes, on every provider, unless BitMapVectorPathStyle.Color is set. |
| `--bit-Map-cluster-background` | --bit-clr-pri | Fill of the cluster bubbles, unless BitMapClustering.Color is set. |
| `--bit-Map-cluster-color` | --bit-clr-pri-text | Count inside the cluster bubbles, unless BitMapClustering.TextColor is set. |
| `--bit-Map-cluster-border-color` | --bit-clr-ntr-white | Ring around the cluster bubbles. |
## Examples
\n**Basic**:
```razor
```
\n**Markers**:
```razor
Add a marker
Open London's popup
Close the popup
Fit to markers
Clear
markersMapRef = default!;
private readonly BitLeafletMapProvider markersProvider = new() { Center = new(48.8566, 2.3522), Zoom = 5 };
private string markersLog = "Click, hover or drag a marker.";
private int markerCounter;
private async Task OnMarkersReady()
{
await markersMapRef.SyncMarkers(
[
new() { Id = "paris", Position = new(48.8566, 2.3522), Alt = "Paris", PopupText = "Paris - click a marker to open its popup.", TooltipText = "Paris" },
new() { Id = "london", Position = new(51.5074, -0.1278), Alt = "London", PopupText = "London - drag me.", TooltipText = "Drag me", Draggable = true },
]);
await markersMapRef.FitBoundsToMarkers();
}
private async Task AddRandomMarker()
{
// Somewhere inside the current view, so the new marker is always visible.
var view = await markersMapRef.GetView();
var bounds = view.Bounds;
var lat = bounds.SouthWest.Latitude + (0.1 + Random.Shared.NextDouble() * 0.8) * bounds.LatitudeSpan;
var lng = bounds.SouthWest.Longitude + (0.1 + Random.Shared.NextDouble() * 0.8) * bounds.LongitudeSpan;
var position = new BitMapLatLng(lat, lng > 180 ? lng - 360 : lng); // a view across the antimeridian
var id = $"marker-{++markerCounter}";
await markersMapRef.AddMarker(new BitMapMarker
{
Id = id,
Position = position,
Alt = $"Marker {markerCounter}",
PopupText = $"Marker {markerCounter} at {position.Latitude:F4}, {position.Longitude:F4}",
TooltipText = $"Marker {markerCounter}",
});
markersLog = $"Added {id}.";
}
private async Task OpenLondonPopup() => await markersMapRef.OpenMarkerPopup("london");
private async Task ClosePopup() => markersLog = await markersMapRef.CloseMarkerPopup() ? "Popup closed." : "No popup was open.";
private async Task FitToMarkers() => await markersMapRef.FitBoundsToMarkers();
private async Task ClearMarkers()
{
await markersMapRef.ClearMarkers();
markersLog = "All markers removed.";
}
private void OnMarkerClick(string id) => markersLog = $"Clicked {id}.";
private void OnMarkerDragEnd(BitMapMarkerDragEndArgs e) => markersLog = $"Dropped {e.Id} at {e.Position.Latitude:F4}, {e.Position.Longitude:F4}.";
```
\n**Data binding**:
```razor
Rome
Paris
Add a marker
Move the first marker
boundMarkers =
[
new() { Id = "rome", Position = new(41.9028, 12.4964), Alt = "Rome", PopupText = "Rome" },
new() { Id = "paris", Position = new(48.8566, 2.3522), Alt = "Paris", PopupText = "Paris" },
];
private int boundMarkerCounter;
private void AddBoundMarker()
{
var id = $"marker-{++boundMarkerCounter}";
// A new list: the parameter is compared by reference, the markers in it by value.
boundMarkers = [.. boundMarkers, new BitMapMarker
{
Id = id,
Position = boundCenter ?? new(0, 0),
Alt = $"Marker {boundMarkerCounter}",
PopupText = $"Marker {boundMarkerCounter}",
}];
}
private void MoveFirstBoundMarker()
{
if (boundMarkers.Count == 0) return;
var first = boundMarkers[0];
boundMarkers = [first with { Position = first.Position.Offset(100_000, 45) }, .. boundMarkers.Skip(1)];
}
```
\n**Marker icons**:
```razor
```
```csharp
private BitMap iconsMapRef = default!;
private readonly BitLeafletMapProvider iconsProvider = new() { Center = new(51.5045, -0.0865), Zoom = 15 };
private bool iconCentreAnchor = true;
private List iconMarkers = BuildIconMarkers(true);
// The coordinate the disc stands for, marked by a ring so the anchoring can be seen.
private static readonly BitMapLatLng iconProbe = new(51.5045, -0.0865);
private static string DiscIcon(string fill) => "data:image/svg+xml;charset=utf-8," + Uri.EscapeDataString(
$"""""");
private async Task OnIconsReady()
{
await iconsMapRef.AddCircle("probe", iconProbe, 12, new() { Color = "#111", Weight = 2, Fill = false });
}
private void ToggleIconAnchor(bool centred)
{
iconCentreAnchor = centred;
iconMarkers = BuildIconMarkers(centred);
}
private static List BuildIconMarkers(bool centred) =>
[
// The default pin, in the theme's primary color - or any other, a theme variable included.
new() { Id = "pin", Position = iconProbe.Offset(110, 300), Alt = "Pin in the primary color" },
new() { Id = "pin-sec", Position = iconProbe.Offset(110, 240), Alt = "Pin in the secondary color", Color = "var(--bit-clr-sec)" },
// A disc stands for the coordinate at its centre, so it has to say so.
new()
{
Id = "disc", Position = iconProbe, Alt = centred ? "Disc, anchored at its centre" : "Disc, on the default anchor",
IconUrl = DiscIcon(centred ? "#107c10" : "#8a8886"), IconWidth = 28, IconHeight = 28,
IconAnchorX = centred ? 14 : null, IconAnchorY = centred ? 14 : null,
},
];
```
\n**Popup content**:
```razor
popupMarkers =
[
new() { Id = "opera", Position = new(48.2029, 16.3690), Alt = "Vienna State Opera" },
new() { Id = "prater", Position = new(48.2166, 16.3960), Alt = "Prater" },
new() { Id = "belvedere", Position = new(48.1915, 16.3809), Alt = "Belvedere" },
];
private readonly Dictionary popupVisits = [];
private string popupLog = "Click a marker, then the button in its popup.";
private int GetVisitorCount(string markerId) => popupVisits.GetValueOrDefault(markerId);
// An event handler inside the popup - which an HTML-string popup cannot have.
private void RecordVisit(string markerId)
{
popupVisits[markerId] = GetVisitorCount(markerId) + 1;
popupLog = $"Recorded a visit to {markerId}.";
}
private void OnPopupOpened(BitMapMarker marker) => popupLog = $"Opened the popup of {marker.Alt}.";
```
\n**Clustering**:
```razor
Scatter again
clusterMarkers = ScatterMarkers();
private string clusterLog = "Click a bubble to zoom into it.";
private void ToggleClustering(bool enabled)
{
clusterEnabled = enabled;
// Null turns clustering off and hands every marker back to the provider.
clusterOptions = enabled ? new() { RadiusPixels = 60, MaxZoom = 14 } : null;
}
private void RegenerateClusterMarkers() => clusterMarkers = ScatterMarkers();
private static List ScatterMarkers()
{
(string Name, double Lat, double Lng, int Count)[] cities =
[
("London", 51.5074, -0.1278, 160), ("Paris", 48.8566, 2.3522, 120), ("Berlin", 52.5200, 13.4050, 90),
("Madrid", 40.4168, -3.7038, 70), ("Rome", 41.9028, 12.4964, 60),
];
return [.. cities.SelectMany(c => Enumerable.Range(1, c.Count).Select(i => new BitMapMarker
{
Id = $"{c.Name}-{i}",
Position = new(c.Lat + (Random.Shared.NextDouble() - 0.5) * 2.5, c.Lng + (Random.Shared.NextDouble() - 0.5) * 2.5),
Alt = $"{c.Name} location {i}",
PopupText = $"{c.Name} #{i}",
}))];
}
private void OnClusterClick(BitMapClusterClickArgs e) => clusterLog = $"A bubble of {e.Count} markers - zoomed to fit them.";
private void OnClusterMarkerClick(string id) => clusterLog = $"Clicked {id}.";
```
\n**Vector layers**:
```razor
Draw shapes
Load GeoJSON
Clear
vectorsMapRef = default!;
private readonly BitLeafletMapProvider vectorsProvider = new() { Center = new(37.7749, -122.4194), Zoom = 12 };
private string vectorsLog = "Click a shape.";
private async Task DrawVectors()
{
await vectorsMapRef.ClearVectorLayers();
await vectorsMapRef.AddPolyline("route", [new(37.80, -122.42), new(37.79, -122.41), new(37.78, -122.40), new(37.77, -122.395)],
new() { Color = "#d13438", Weight = 5 });
await vectorsMapRef.AddPolygon("park", [new(37.769, -122.486), new(37.771, -122.475), new(37.765, -122.472), new(37.762, -122.482)],
new() { Color = "#107c10", FillOpacity = 0.35, Weight = 2 });
await vectorsMapRef.AddCircle("radius", new(37.7849, -122.4094), 900,
new() { Color = "#0065ef", FillOpacity = 0.15, Weight = 2 });
await vectorsMapRef.AddRectangle("box", new(new(37.748, -122.44), new(37.756, -122.42)),
new() { Color = "#c19c00", FillOpacity = 0.12, Weight = 2, DashArray = "6 4" });
await vectorsMapRef.FitBounds(new(new(37.755, -122.49), new(37.805, -122.38)));
vectorsLog = "Four shapes drawn. Click one.";
}
private async Task LoadGeoJson()
{
await vectorsMapRef.ClearVectorLayers();
await vectorsMapRef.AddGeoJson("nyc", sampleGeoJson, new() { Color = "#8764b8", Weight = 3, FillOpacity = 0.25 });
await vectorsMapRef.FitBounds(new(new(40.70, -74.01), new(40.81, -73.95)));
vectorsLog = "GeoJSON loaded. Click a feature.";
}
private async Task ClearVectors()
{
await vectorsMapRef.ClearVectorLayers();
vectorsLog = "All vector layers removed.";
}
private void OnVectorClick(BitMapVectorClickArgs e) => vectorsLog = $"Clicked the {e.Kind} \"{e.LayerId}\".";
private void OnGeoJsonFeatureClick(BitMapGeoJsonFeatureClickArgs e)
{
// The properties are whatever the document carries - read them as data, never render them as HTML.
var name = e.Properties.TryGetProperty("name", out var value) ? value.ToString() : "(unnamed)";
vectorsLog = $"Clicked the feature \"{name}\" of the layer \"{e.LayerId}\".";
}
private const string sampleGeoJson = """
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "name": "Central Park" },
"geometry": { "type": "Polygon", "coordinates": [[[-73.981, 40.768], [-73.958, 40.768], [-73.958, 40.800], [-73.981, 40.800], [-73.981, 40.768]]] }
},
{
"type": "Feature",
"properties": { "name": "Brooklyn Bridge" },
"geometry": { "type": "LineString", "coordinates": [[-73.9969, 40.7061], [-73.9875, 40.7026]] }
}
]
}
""";
```
\n**Layers**:
```razor
OpenStreetMap
Carto Voyager
OpenTopoMap
@(layerVisible ? "Hide the area" : "Show the area")
Restyle the area
@(overlayVisible ? "Hide the labels" : "Show the labels")
@(overlayDimmed ? "Brighten the labels" : "Dim the labels")
layersMapRef = default!;
private string basemap = "osm";
private BitLeafletMapProvider layersProvider = new() { Center = new(51.5074, -0.1278), Zoom = 11 };
private bool layerVisible = true;
private bool overlayVisible = true;
private bool overlayDimmed;
private int layerStyleIndex;
private string layersLog = "Switch the basemap, or change the area and the labels.";
private static readonly BitMapVectorPathStyle[] layerStyles =
[
new() { Color = "#0065ef", FillOpacity = 0.2, Weight = 3 },
new() { Color = "#d13438", FillOpacity = 0.3, Weight = 5, DashArray = "6 4" },
new() { Color = "#107c10", Fill = false, Weight = 4 },
];
private void SetBasemap(string name)
{
basemap = name;
// A new instance is what pushes the change: the provider is compared by reference.
layersProvider = name switch
{
"carto" => new()
{
Center = new(51.5074, -0.1278), Zoom = 11,
TileUrl = "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
TileAttribution = "© OpenStreetMap contributors © CARTO",
},
"topo" => new()
{
Center = new(51.5074, -0.1278), Zoom = 11, TileMaxZoom = 17,
TileUrl = "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
TileAttribution = "Map data: © OpenStreetMap contributors, SRTM | Map style: © OpenTopoMap",
},
_ => new() { Center = new(51.5074, -0.1278), Zoom = 11 },
};
}
private async Task OnLayersReady()
{
await layersMapRef.AddCircle("area", new(51.5074, -0.1278), 6000, layerStyles[0]);
await layersMapRef.AddTileOverlay(new()
{
Id = "labels",
UrlTemplate = "https://tiles.stadiamaps.com/tiles/stamen_toner_labels/{z}/{x}/{y}{r}.png",
Attribution = "Map tiles by Stamen Design, hosted by Stadia Maps. Data by OpenStreetMap.",
Opacity = 0.8,
MinZoom = 3,
});
}
private async Task ToggleLayerVisibility()
{
layerVisible = !layerVisible;
await layersMapRef.SetLayerVisible("area", layerVisible);
layersLog = layerVisible ? "The area is back, as it was defined." : "The area is hidden - and takes no clicks.";
}
private async Task CycleLayerStyle()
{
layerStyleIndex = (layerStyleIndex + 1) % layerStyles.Length;
await layersMapRef.SetLayerStyle("area", layerStyles[layerStyleIndex]);
layersLog = $"Restyled the area (style {layerStyleIndex + 1} of {layerStyles.Length}).";
}
private async Task ToggleOverlayVisibility()
{
overlayVisible = !overlayVisible;
await layersMapRef.SetTileOverlayVisible("labels", overlayVisible);
layersLog = overlayVisible ? "The labels are shown." : "The labels are hidden.";
}
private async Task ToggleOverlayOpacity()
{
overlayDimmed = !overlayDimmed;
await layersMapRef.SetTileOverlayOpacity("labels", overlayDimmed ? 0.25 : 0.8);
layersLog = overlayDimmed ? "The labels are dimmed." : "The labels are bright again.";
}
```
\n**Camera & events**:
```razor
Fly to Tokyo
Zoom 6
Locate me
Log the viewport
eventsMapRef = default!;
private readonly BitLeafletMapProvider eventsProvider = new() { Center = new(41.9028, 12.4964), Zoom = 5 };
private string eventsLog = "Click, double-click or right-click the map, or pan it.";
private void OnMapClick(BitMapLatLng p) => eventsLog = $"Click at {p.Latitude:F4}, {p.Longitude:F4}";
private void OnMapDoubleClick(BitMapLatLng p) => eventsLog = $"Double-click at {p.Latitude:F4}, {p.Longitude:F4}";
private void OnMapContextMenu(BitMapLatLng p) => eventsLog = $"Right-click at {p.Latitude:F4}, {p.Longitude:F4}";
private void OnViewChanged(BitMapViewState v) => eventsLog = $"View settled: zoom {v.Zoom:F1}, centre {v.Center.Latitude:F4}, {v.Center.Longitude:F4}";
private async Task FlyToTokyo() => await eventsMapRef.FlyTo(new(35.6762, 139.6503), 11);
private async Task ZoomToSix() => await eventsMapRef.SetZoom(6);
private async Task LocateMe()
{
var result = await eventsMapRef.Locate(new() { Zoom = 13 });
eventsLog = result is null
? "The browser refused the location request, or it timed out."
: $"Located at {result.Position.Latitude:F4}, {result.Position.Longitude:F4} (±{result.AccuracyMeters:F0} m)";
}
private async Task ReadView()
{
var v = await eventsMapRef.GetView();
eventsLog = $"Zoom {v.Zoom:F2}, centre {v.Center.Latitude:F4}, {v.Center.Longitude:F4}, " +
$"bounds {v.Bounds.SouthWest.Latitude:F2}, {v.Bounds.SouthWest.Longitude:F2} - {v.Bounds.NorthEast.Latitude:F2}, {v.Bounds.NorthEast.Longitude:F2}";
}
```
\n**Interaction**:
```razor
```
```csharp
private bool interScrollWheel = true;
private bool interDragging = true;
private bool interScaleBar = true;
private bool interMaxBounds;
private bool interDisabled;
private BitLeafletMapProvider interProvider = new() { Center = new(51.5074, -0.1278), Zoom = 10, ShowScaleControl = true };
private void BuildInteractionProvider()
{
interProvider = new()
{
Center = new(51.5074, -0.1278), Zoom = 10,
ScrollWheelZoom = interScrollWheel,
Dragging = interDragging,
ShowScaleControl = interScaleBar,
MaxBounds = interMaxBounds ? new(new(51.25, -0.55), new(51.75, 0.35)) : null,
};
}
```
\n**Custom controls**:
```razor
```
```csharp
private BitMap controlsMapRef = default!;
// The provider's own zoom buttons are turned off - the toolbar replaces them.
private readonly BitLeafletMapProvider controlsProvider = new() { Center = new(40.4168, -3.7038), Zoom = 11, ZoomControl = false };
private bool isFullscreen;
```
\n**Geographic helpers**:
```razor
Fit to the markers
Frame 5 km around Big Ben
Where is Big Ben on screen?
geoMapRef = default!;
private readonly BitLeafletMapProvider geoProvider = new() { Center = new(51.5045, -0.0865), Zoom = 12 };
private string geoLog = "Click the map to drop a probe.";
private static readonly BitMapLatLng bigBen = new(51.5007, -0.1246);
private readonly List geoMarkers =
[
new() { Id = "bigben", Position = bigBen, Alt = "Big Ben", TooltipText = "Big Ben" },
new() { Id = "tower", Position = new(51.5055, -0.0754), Alt = "Tower Bridge", TooltipText = "Tower Bridge" },
new() { Id = "eye", Position = new(51.5033, -0.1196), Alt = "London Eye", TooltipText = "London Eye" },
];
private void OnGeoMapClick(BitMapLatLng point)
{
var box = BitMapLatLngBounds.FromMarkers(geoMarkers);
geoLog = $"{bigBen.DistanceTo(point) / 1000:F2} km from Big Ben, {(box.Contains(point) ? "inside" : "outside")} the markers' box.";
}
private async Task FitGeoMarkers()
{
// Padded in map units, and capped so three nearby markers do not zoom to street level.
await geoMapRef.FitBounds(BitMapLatLngBounds.FromMarkers(geoMarkers).Pad(0.15), paddingPixels: 24, maxZoom: 15);
geoLog = "Fitted the view to the markers.";
}
private async Task FitGeoRadius()
{
await geoMapRef.FitBounds(bigBen.ToBounds(5_000), maxZoom: 16);
geoLog = "Framed everything within 5 km of Big Ben.";
}
private async Task ProjectGeoOrigin()
{
var point = await geoMapRef.Project(bigBen);
geoLog = point is null ? "Big Ben is off screen." : $"Big Ben is at {point.Value.X:F0}, {point.Value.Y:F0} px inside the map.";
}
```
\n**Accessibility**:
```razor
```
```csharp
private bool a11yCooperative = true;
private bool a11yAnnounce = true;
private bool a11yShowList = true;
private readonly BitLeafletMapProvider a11yProvider = new() { Center = new(52.5180, 13.3950), Zoom = 13 };
// Every marker has an Alt: it is the marker's accessible name and its name in the table.
private readonly List a11yMarkers =
[
new() { Id = "gate", Position = new(52.5163, 13.3777), Alt = "Brandenburg Gate", PopupText = "Brandenburg Gate" },
new() { Id = "island", Position = new(52.5169, 13.4019), Alt = "Museum Island", PopupText = "Museum Island" },
new() { Id = "tower", Position = new(52.5208, 13.4094), Alt = "TV Tower", PopupText = "TV Tower" },
];
// A real app would reverse-geocode the centre into a place name here.
private static string FormatAnnouncement(BitMapViewState view) => $"Central Berlin at zoom {view.Zoom:F0}.";
```
\n**Loading and lifecycle**:
```razor
Fetching the basemap…
```
```csharp
private BitMapLoadState lifecycleState = BitMapLoadState.Idle;
private readonly BitLeafletMapProvider lifecycleProvider = new() { Center = new(59.9139, 10.7522), Zoom = 10 };
```
\n**Providers**:
```razor
> providerItems =
[
new() { Text = "Leaflet", Value = "leaflet" },
new() { Text = "MapLibre GL", Value = "maplibre" },
new() { Text = "OpenLayers", Value = "openlayers" },
new() { Text = "ArcGIS", Value = "arcgis" },
new() { Text = "CesiumJS", Value = "cesium" },
];
private readonly BitLeafletMapProvider leafletProvider = new() { Center = new(48.8566, 2.3522), Zoom = 5 };
private readonly BitMapLibreMapProvider maplibreProvider = new() { Center = new(48.8566, 2.3522), Zoom = 3 };
private readonly BitOpenLayersMapProvider olProvider = new() { Center = new(48.8566, 2.3522), Zoom = 5 };
// The osm basemap needs no key; any other needs an API key restricted to your domains.
private readonly BitArcGisMapProvider arcGisProvider = new() { Center = new(48.8566, 2.3522), Zoom = 5, BasemapId = "osm" };
private readonly BitCesiumMapProvider cesiumProvider = new() { Center = new(48.8566, 2.3522), Zoom = 3, SceneMode = "scene3d" };
```
\n**Cascading parameters**:
```razor
```
```csharp
private readonly BitLeafletMapProvider paramsProvider1 = new() { Center = new(52.3676, 4.9041), Zoom = 12 };
private readonly BitLeafletMapProvider paramsProvider2 = new() { Center = new(38.7223, -9.1393), Zoom = 12 };
private readonly BitMapParams[] mapParams =
[
new()
{
CooperativeGestures = true,
CooperativeGesturesWheelHint = "Hold ctrl while scrolling to zoom",
KeyboardInstructions = "Arrows pan, plus and minus zoom, Escape leaves.",
Style = "--bit-Map-radius: 0.75rem; --bit-Map-border: 1px solid var(--bit-clr-brd-sec)",
}
];
```
\n**Style & Class**:
```razor
```
```csharp
private readonly BitLeafletMapProvider styleProvider = new() { Center = new(45.4642, 9.1900), Zoom = 12 };
private readonly BitLeafletMapProvider classProvider = new() { Center = new(45.4642, 9.1900), Zoom = 12 };
private readonly List styleMarkers =
[
new() { Id = "duomo", Position = new(45.4642, 9.1916), Alt = "Duomo", PopupText = "Duomo di Milano", TooltipText = "Duomo" },
new() { Id = "scala", Position = new(45.4674, 9.1895), Alt = "La Scala", PopupText = "Teatro alla Scala", TooltipText = "La Scala" },
new() { Id = "galleria", Position = new(45.4659, 9.1900), Alt = "Galleria", PopupText = "Galleria Vittorio Emanuele II", TooltipText = "Galleria" },
new() { Id = "castello", Position = new(45.4705, 9.1793), Alt = "Castello", PopupText = "Castello Sforzesco", TooltipText = "Castello" },
new() { Id = "brera", Position = new(45.4719, 9.1879), Alt = "Brera", PopupText = "Pinacoteca di Brera", TooltipText = "Brera" },
];
```
`BitMapDemo.razor.scss`:
```scss
::deep {
.custom-map {
border: 2px dashed var(--bit-clr-err);
border-radius: 0.5rem;
}
.custom-map-canvas {
--bit-Map-tile-filter: saturate(0.3);
}
}
```
\n**RTL**:
```razor
```
```csharp
private readonly BitLeafletMapProvider rtlProvider = new() { Center = new(35.6892, 51.3890), Zoom = 11 };
```
@markersLog``` ```csharp private BitMap
Centre @boundCenter?.Latitude.ToString("F4"), @boundCenter?.Longitude.ToString("F4") - zoom @boundZoom?.ToString("F1") - @boundMarkers.Count marker(s)
```
```csharp
private BitMapLatLng? boundCenter = new(41.9028, 12.4964);
private double? boundZoom = 5;
private List
@marker.Alt
Record a visit
Visitors this month: @GetVisitorCount(marker.Id)
@popupLog``` ```csharp private readonly BitLeafletMapProvider popupProvider = new() { Center = new(48.2082, 16.3738), Zoom = 12 }; private readonly List
@clusterLog``` ```csharp private readonly BitLeafletMapProvider clusterProvider = new() { Center = new(48.5, 5), Zoom = 4 }; private bool clusterEnabled = true; private BitMapClustering? clusterOptions = new() { RadiusPixels = 60, MaxZoom = 14 }; private List
@vectorsLog``` ```csharp private BitMap
@layersLog``` ```csharp private BitMap
@eventsLog``` ```csharp private BitMap
@geoLog``` ```csharp private BitMap
State: @lifecycleState
@switch (providerName)
{
case "maplibre":
break;
case "openlayers":
break;
case "arcgis":
break;
case "cesium":
break;
default:
break;
}
```
```csharp
private string providerName = "leaflet";
private readonly Listتهران