๐บ๏ธ Blazor interop for Google Maps JavaScript API
A powerful and easy-to-use Blazor library for integrating Google Maps into your Blazor WebAssembly and Blazor Server applications.
- Features
- Prerequisites
- Installation
- Quick Start
- Configuration
- Usage Examples
- Live Demos
- Breaking Changes
- Contributing
- ๐ฏ Full Google Maps API Support - Markers, Polylines, Polygons, Circles, Info Windows, and more
- ๐ Blazor WebAssembly & Server - Works seamlessly with both hosting models
- ๐จ Advanced Markers - Render Blazor components directly on the map
- ๐ Marker Clustering - Built-in support for marker clustering
- ๐ฅ Heat Maps - Visualize data density with heat map layers
- ๐ฃ๏ธ Directions & Routes - Full support for directions and route rendering
- ๐ญ Map Styling - Customize map appearance with style options
- ๐ Data Layers - Support for GeoJSON and other data formats
- โก Event Handling - Comprehensive event support for interactive maps
- ๐จ Drawing Tools - Built-in drawing manager for shapes and overlays
- ๐ผ๏ธ Static Maps - Render maps as plain images, with no JavaScript involved
- .NET 8.0 or higher
- A valid Google Maps API key (Get one here)
Install the package via NuGet Package Manager:
dotnet add package BlazorGoogleMapsOr via NuGet Package Manager Console:
Install-Package BlazorGoogleMapsAdd BlazorGoogleMaps to your Program.cs:
builder.Services.AddBlazorGoogleMaps("YOUR_GOOGLE_API_KEY");builder.Services.AddBlazorGoogleMaps(new GoogleMapsComponents.Maps.MapApiLoadOptions("YOUR_GOOGLE_API_KEY")
{
Version = "beta",
Libraries = "places,visualization,drawing,marker"
});For more complex scenarios (e.g., loading keys asynchronously from a database):
builder.Services.AddScoped<IBlazorGoogleMapsKeyService, YourCustomKeyService>();
โ ๏ธ Legacy Method (Not Recommended): Adding the script tag directly to your HTML is still supported but not recommended.
Add the required JavaScript files to your wwwroot/index.html (Blazor WASM) or _Host.cshtml/_HostLayout.cshtml (Blazor Server):
<script src="_content/BlazorGoogleMaps/js/objectManager.js"></script>Optional: For marker clustering support, add:
<script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>Create a simple map component:
@page "/map"
@using GoogleMapsComponents
@using GoogleMapsComponents.Maps
<h1>Google Map</h1>
<div style="height: 500px;">
<GoogleMap @ref="@_map1"
Id="map1"
Options="@_mapOptions"
Height="100%"
OnAfterInit="@AfterMapRender">
</GoogleMap>
</div>
@code {
private GoogleMap? _map1;
private MapOptions _mapOptions = default!;
protected override void OnInitialized()
{
_mapOptions = new MapOptions()
{
Zoom = 13,
Center = new LatLngLiteral()
{
Lat = 13.505892,
Lng = 100.8162
},
MapTypeId = MapTypeId.Roadmap
};
}
private async Task AfterMapRender()
{
// Map is ready - you can perform additional initialization here
var bounds = await LatLngBounds.CreateAsync(_map1!.JsRuntime);
}
}Render interactive Blazor components as markers (requires Google Maps v=beta and a MapId):
@page "/advanced-map"
@using GoogleMapsComponents
@using GoogleMapsComponents.Maps
<h1>Advanced Map with Blazor Markers</h1>
<AdvancedGoogleMap @ref="@_map1" Id="map1" Options="@_mapOptions">
@foreach (var marker in Markers)
{
<MarkerComponent
@key="marker.Id"
Lat="@marker.Lat"
Lng="@marker.Lng"
Clickable="@marker.Clickable"
Draggable="@marker.Draggable"
OnClick="@(() => marker.Active = !marker.Active)"
OnMove="@(pos => marker.UpdatePosition(pos))">
<div class="custom-marker">
<h4>@marker.Title</h4>
<p>Custom Blazor Content</p>
</div>
</MarkerComponent>
}
</AdvancedGoogleMap>
@code {
private AdvancedGoogleMap? _map1;
private List<MarkerData> Markers =
[
new MarkerData { Id = 1, Lat = 13.505892, Lng = 100.8162, Title = "Location 1" }
];
private MapOptions _mapOptions = new()
{
Zoom = 13,
Center = new LatLngLiteral()
{
Lat = 13.505892,
Lng = 100.8162
},
MapId = "DEMO_MAP_ID", // Required for advanced markers
MapTypeId = MapTypeId.Roadmap
};
public class MarkerData
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public double Lat { get; set; }
public double Lng { get; set; }
public bool Clickable { get; set; } = true;
public bool Draggable { get; set; }
public bool Active { get; set; }
public void UpdatePosition(LatLngLiteral position)
{
Lat = position.Lat;
Lng = position.Lng;
}
}
}The Maps Static API returns a map as an ordinary image. No JavaScript is loaded and no interop object is created, which makes it a good fit for thumbnails, previews, e-mails, print views and pages that must stay lightweight. The trade-off is that the result is a picture: it cannot be panned or zoomed.
@page "/static-map"
@using GoogleMapsComponents.Maps
@using GoogleMapsComponents.Maps.StaticMaps
<StaticMap Options="@_options" Alt="Map of Bangkok" class="border" />
@code {
private StaticMapOptions _options = new()
{
Center = new LatLngLiteral(13.505892, 100.8162),
Zoom = 13,
Width = 600,
Height = 400,
MapType = MapTypeId.Roadmap
};
}Markers, paths and polygons are added through the options. Locations accept either coordinates or a geocodable
address, and locations that share a style belong in a single StaticMapMarker so that the URL stays short:
var options = new StaticMapOptions
{
Width = 600,
Height = 400,
Markers =
[
new StaticMapMarker(new LatLngLiteral(13.7563, 100.5018), new LatLngLiteral(13.7367, 100.5232))
{
Color = StaticMapColors.Blue,
Size = StaticMapMarkerSize.Mid
},
new StaticMapMarker("Don Mueang International Airport, Bangkok") { Label = 'A' }
],
Paths =
[
// Encode = true compresses the points, which matters because a request URL is limited to 16384 characters.
new StaticMapPath(routePoints) { Encode = true, Color = "#0000FF", Weight = 4 },
// A path with a FillColor becomes a polygon; the API closes it for you.
new StaticMapPath(areaPoints) { Color = "0x00000000", FillColor = "0xFF000033" }
],
// Built with the same GoogleMapStyleBuilder as an interactive map.
Styles = new GoogleMapStyleBuilder()
.AddColor(MapStyleFeatures.Water, MapStyleElements.Geometry, "#1d2c4d")
.AddVisibility(MapStyleFeatures.Poi, MapStyleElements.Labels, false)
.Build()
};To build a URL outside of a component โ to embed a map in an e-mail, a PDF or a report โ inject
StaticMapService, which is registered by AddBlazorGoogleMaps and uses the same API key as the rest of the
library:
@inject StaticMapService StaticMaps
var url = await StaticMaps.GetUrlAsync(options);EncodedPolyline accepts an already encoded polyline, so the OverviewPolyline of a route returned by the
Directions API can be drawn on a static map directly. PolylineEncoder encodes and decodes those values.
Requests may optionally be signed. Signing needs the URL signing secret, which must never be shipped to a
browser, so StaticMapUrlSigner.Sign and StaticMapService.GetSignedUrlAsync belong in server-side code only.
Explore interactive examples and learn more features:
- ๐ Server-Side Demo: GitHub Repository
- ๐ Client-Side Demo: Live Demo
The server-side demos include the most up-to-date examples covering:
- Markers and Info Windows
- Polylines, Polygons, and Circles
- Heat Maps and Data Layers
- Drawing Manager
- Routes and Directions
- Event Handling
- Map Styling
- And much more!
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License.
- Built with โค๏ธ for the Blazor community
- Powered by the Google Maps JavaScript API
Happy Mapping! ๐บ๏ธ