diff --git a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs index 31dc224bc..19796ed60 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs +++ b/BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs @@ -37,6 +37,7 @@ internal override IEnumerable GetNavItems() new (){ Id = "508", Text = "Collapse", Href = "/collapse", IconName = IconName.ArrowsCollapse, ParentId = "5" }, new (){ Id = "509", Text = "Confirm Dialog", Href = "/confirm-dialog", IconName = IconName.QuestionDiamondFill, ParentId = "5" }, new (){ Id = "510", Text = "Dropdown", Href = "/dropdown", IconName = IconName.MenuButtonWideFill, ParentId = "5" }, + new (){ Id = "510", Text = "Google Maps", Href = "/google-maps", IconName = IconName.Map, ParentId = "5" }, #region Grid diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor index 7623fba88..df499566d 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Index.razor @@ -105,6 +105,11 @@

Dropdown

+
+ +

Google Maps New

+
+

Grid Updated

diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDemoComponentBase.cs b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDemoComponentBase.cs new file mode 100644 index 000000000..b1724a7bf --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDemoComponentBase.cs @@ -0,0 +1,14 @@ +namespace BlazorBootstrap.Demo.RCL; + +public class GoogleMapDemoComponentBase : ComponentBase +{ + public string ApiKey = default!; + + [Inject] private IConfiguration Configuration { get; set; } = default!; + + protected override void OnInitialized() + { + ApiKey = Configuration["GoogleMap:ApiKey"].ToString(); + base.OnInitialized(); + } +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor new file mode 100644 index 000000000..2b9759f02 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMapDocumentation.razor @@ -0,0 +1,67 @@ +@page "/google-maps" + +@title + + + +

Blazor Google Map

+
+ Blazor Bootstrap Google Map component will create maps to show locations anywhere in the world using the Google JavaScript API. +
+ + + + +
+ Before you start using the GoogleMap component in your project, you need an API key. + Please follow the link below for detailed steps. + Link: https://developers.google.com/maps/documentation/javascript/adding-a-google-map#key. +
+ + +
This example demonstrates how to use a simple Google Maps component.
+ + + +
This example demonstrates how to use a simple Google Maps component with marker.
+ + + + +
To scale a marker, use the PinElement.Scale option.
+ + +
Use the PinElement.Background option to change the background color of a marker.
+ + +
Use the PinElement.BorderColor option to change the border color of a marker.
+ + +
Use the PinElement.GlyphColor option to change the glyph color of a marker.
+ + +
Set the PinElement.Glyph option to an empty string to hide a marker's glyph.
+ + +
Use the PinElement.UseIconFonts and PinElement.Glyph options to use the icon fonts.
+ + + + + + +
+ This example shows you how to make markers respond to click events. To make a marker clickable: + Set the Clickable parameter to true. +
+ + + + + +@code { + private string pageUrl = "/google-maps"; + private string title = "Blazor Google Map Component"; + private string description = "Blazor Bootstrap Google Map component will create maps to show locations anywhere in the world using the Google JavaScript API."; + private string imageUrl = "https://i.imgur.com/AbyDP51.png"; +} diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor new file mode 100644 index 000000000..16b50dc0d --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_01_Examples.razor @@ -0,0 +1,7 @@ +@inherits GoogleMapDemoComponentBase + + \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_02_Marker.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_02_Marker.razor new file mode 100644 index 000000000..7eb3d7404 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_02_Marker.razor @@ -0,0 +1,24 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor new file mode 100644 index 000000000..13f6a4e14 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_A_Scale_the_marker.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement{ Scale = 1.5 }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + PinElement = new PinElement{ Scale = 1.5 }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor new file mode 100644 index 000000000..02e59c8d0 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_B_Change_the_background_color.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement{ Background = "#FBBC04", }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + PinElement = new PinElement{ Background = "#FBBC04", }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor new file mode 100644 index 000000000..a507feee4 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_C_Change_the_border_color.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement{ BorderColor = "#137333", }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + PinElement = new PinElement{ BorderColor = "#137333", }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor new file mode 100644 index 000000000..9f298a3d8 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_D_Change_the_glyph_color.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement{ GlyphColor = "white", }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + PinElement = new PinElement{ GlyphColor = "white", }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor new file mode 100644 index 000000000..a80d26525 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_E_Hide_the_glyph.razor @@ -0,0 +1,26 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement{ Glyph = "", }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352) , + Title = "Single family house with modern design", + }, + new GoogleMapMarker() + { + PinElement = new PinElement{ Glyph = "", }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727) , + Title = "Townhouse with friendly neighbors", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor new file mode 100644 index 000000000..8402fd1c3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_03_Marker_Customization_F_Use_icon_fonts.razor @@ -0,0 +1,110 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.39561833718522, -122.21855116258479), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.423928529779644, -122.1087629822001), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.40578635332598, -122.15043378466069), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.36399747905774, -122.10465384268522), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.38343706184458, -122.02340436985183), + Title = "Heavy rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.34576403052, -122.04455090047453), + Title = "Heavy rain", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor new file mode 100644 index 000000000..51e78a200 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_04_Markers_with_HTML_and_CSS.razor @@ -0,0 +1,32 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + List markers = new() + { + new GoogleMapMarker() + { + Content = "", + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Drizzle" + }, + new GoogleMapMarker() + { + Content = "", + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Lightning rain" + }, + new GoogleMapMarker() + { + Content = "", + Position = new GoogleMapMarkerPosition(37.39561833718522, -122.21855116258479), + Title = "Rain" + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor new file mode 100644 index 000000000..b6e5e6476 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_05_Make_a_marker_clickable.razor @@ -0,0 +1,119 @@ +@inherits GoogleMapDemoComponentBase + + + +@code { + [Inject] public ToastService ToastService { get; set; } = default!; + + private void OnGoogleMapMarkerClick(GoogleMapMarker marker) + { + ToastService.Notify(new ToastMessage(ToastType.Success, $"{marker.Title}", $"This is a toast message for a weather forecast. DateTime: {DateTime.Now}")); + } + + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.39561833718522, -122.21855116258479), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.423928529779644, -122.1087629822001), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.40578635332598, -122.15043378466069), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.36399747905774, -122.10465384268522), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.38343706184458, -122.02340436985183), + Title = "Heavy rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.34576403052, -122.04455090047453), + Title = "Heavy rain", + } + }; +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor new file mode 100644 index 000000000..2ac4298d8 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Maps/GoogleMap_Demo_06_Dynamic_markers.razor @@ -0,0 +1,163 @@ +@inherits GoogleMapDemoComponentBase + +
+ + + +
+ + + +@code { + Random random = new Random(2000000000); + GoogleMap googleMapRef = default!; + + [Inject] public ToastService ToastService { get; set; } = default!; + + private async ValueTask AddWeatherMarkerAsync() => await googleMapRef.AddMarkerAsync(GetRandomMarker()); + + private async Task UpdateWeatherMarkersAsync() + { + var markerList = new List + { + GetRandomMarker(), + GetRandomMarker(), + GetRandomMarker(), + GetRandomMarker(), + GetRandomMarker(), + GetRandomMarker(), + }; + await googleMapRef.UpdateMarkersAsync(markerList); + } + + private async Task RefreshMapAsync() + { + markers.Add(GetRandomMarker()); + markers.Add(GetRandomMarker()); + + await googleMapRef.RefreshAsync(); + } + + private void OnGoogleMapMarkerClick(GoogleMapMarker marker) + { + ToastService.Notify(new ToastMessage(ToastType.Success, $"{marker.Title}", $"This is a toast message for a weather forecast. DateTime: {DateTime.Now}")); + } + + List markers = new() + { + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.50024109655184, -122.28528451834352), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-drizzle-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[0].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.44440882321596, -122.2160620727), + Title = "Drizzle", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.39561833718522, -122.21855116258479), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-lightning-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[2].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.423928529779644, -122.1087629822001), + Title = "Lightning rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.40578635332598, -122.15043378466069), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[1].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.36399747905774, -122.10465384268522), + Title = "Rain", + }, + new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor=ColorUtility.CategoricalSixColors[3].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(37.38343706184458, -122.02340436985183), + Title = "Heavy rain", + } + }; + + private GoogleMapMarker GetRandomMarker() + { + var lat = Double.Parse($"37.{random.Next()}"); + var lng = Double.Parse($"-122.{random.Next()}"); + return new GoogleMapMarker() + { + PinElement = new PinElement + { + Glyph = "bi bi-cloud-rain-heavy-fill fs-6 text-white", + UseIconFonts = true, + Background = ColorUtility.CategoricalTwelveColors[9].ToColor().ToRgbaString().ToLowerInvariant(), + BorderColor = ColorUtility.CategoricalTwelveColors[9].ToColor().ToRgbString().ToLowerInvariant() + }, + Position = new GoogleMapMarkerPosition(lat, lng), + Title = "Heavy rain", + }; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.Server/Components/App.razor b/BlazorBootstrap.Demo.Server/Components/App.razor index 48894caed..8b54baf24 100644 --- a/BlazorBootstrap.Demo.Server/Components/App.razor +++ b/BlazorBootstrap.Demo.Server/Components/App.razor @@ -37,6 +37,16 @@ })(window, document, "clarity", "script", "eyusedpimp"); + + @* *@ + diff --git a/BlazorBootstrap.Demo.Server/appsettings.json b/BlazorBootstrap.Demo.Server/appsettings.json index e7bc005c0..2992bc382 100644 --- a/BlazorBootstrap.Demo.Server/appsettings.json +++ b/BlazorBootstrap.Demo.Server/appsettings.json @@ -20,5 +20,8 @@ "github_issues": "//github.com/vikramlearning/blazorbootstrap/issues", "github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions", "stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap" + }, + "GoogleMap": { + "ApiKey": "AIzaSyA-k5n6Q7VzGE-XEDbWFQI4IcgzRrafdy0" } } diff --git a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json index 61eab6f29..38f568a1e 100644 --- a/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json +++ b/BlazorBootstrap.Demo.WebAssembly/wwwroot/appsettings.json @@ -13,5 +13,8 @@ "github_issues": "//github.com/vikramlearning/blazorbootstrap/issues", "github_discussions": "//github.com/vikramlearning/blazorbootstrap/discussions", "stackoverflow": "//stackoverflow.com/questions/tagged/blazor-bootstrap" + }, + "GoogleMap": { + "ApiKey": "AIzaSyA-k5n6Q7VzGE-XEDbWFQI4IcgzRrafdy0" } } \ No newline at end of file diff --git a/blazorbootstrap/Components/Maps/GoogleMap.razor b/blazorbootstrap/Components/Maps/GoogleMap.razor new file mode 100644 index 000000000..e818d82f3 --- /dev/null +++ b/blazorbootstrap/Components/Maps/GoogleMap.razor @@ -0,0 +1,12 @@ +@namespace BlazorBootstrap +@inherits BlazorBootstrapComponentBase + + + + diff --git a/blazorbootstrap/Components/Maps/GoogleMap.razor.cs b/blazorbootstrap/Components/Maps/GoogleMap.razor.cs new file mode 100644 index 000000000..ced5f448e --- /dev/null +++ b/blazorbootstrap/Components/Maps/GoogleMap.razor.cs @@ -0,0 +1,143 @@ +namespace BlazorBootstrap; + +public partial class GoogleMap : BlazorBootstrapComponentBase +{ + #region Fields and Constants + + private DotNetObjectReference? objRef; + + #endregion + + #region Methods + + protected override async Task OnInitializedAsync() + { + objRef ??= DotNetObjectReference.Create(this); + + await base.OnInitializedAsync(); + } + + public ValueTask AddMarkerAsync(GoogleMapMarker marker) + { + JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.addMarker", Id, marker, objRef); + + return ValueTask.CompletedTask; + } + + [JSInvokable] + public async Task OnMarkerClickJS(GoogleMapMarker marker) + { + if (OnMarkerClick.HasDelegate) + await OnMarkerClick.InvokeAsync(marker); + } + + public ValueTask RefreshAsync() + { + JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef); + + return ValueTask.CompletedTask; + } + + public ValueTask UpdateMarkersAsync(IEnumerable markers) + { + JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.updateMarkers", Id, markers, objRef); + + return ValueTask.CompletedTask; + } + + private void OnScriptLoad() + { + Task.Run(async () => await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.googlemaps.initialize", Id, Zoom, Center, Markers, Clickable, objRef)); + } + + #endregion + + #region Properties, Indexers + + protected override string? StyleNames => + BuildStyleNames( + Style, + ($"width:{Width!.Value.ToString(CultureInfo.InvariantCulture)}{WidthUnit.ToCssString()}", Width is not null && Width.Value > 0), + ($"height:{Height!.Value.ToString(CultureInfo.InvariantCulture)}{HeightUnit.ToCssString()}", Height is not null && Height.Value > 0) + ); + + /// + /// Gets or sets the Google Maps API key. + /// + [Parameter] + public string? ApiKey { get; set; } + + /// + /// Gets or sets the center parameter. + /// + [Parameter] + public GoogleMapCenter Center { get; set; } = default!; + + /// + /// Makes the marker clickable if set to . + /// + [Parameter] + public bool Clickable { get; set; } + + private string? GoogleMapsJsFileUrl => $"https://maps.googleapis.com/maps/api/js?key={ApiKey}&libraries=maps,marker"; + + /// + /// Gets or sets the height of the . + /// + /// + /// Default value is . + /// + [Parameter] + public double? Height { get; set; } + + /// + /// Gets or sets the units for the . + /// + /// + /// Default value is . + /// + [Parameter] + public Unit HeightUnit { get; set; } = Unit.Px; + + /// + /// Gets or sets the markers. + /// + [Parameter] + public IEnumerable? Markers { get; set; } + + /// + /// Event fired when a user clicks on a marker. + /// This event fires only when is set to . + /// + [Parameter] + public EventCallback OnMarkerClick { get; set; } + + /// + /// Gets or sets the width of the . + /// + /// + /// Default value is . + /// + [Parameter] + public double? Width { get; set; } + + /// + /// Gets or sets the units for the . + /// + /// + /// Default value is . + /// + [Parameter] + public Unit WidthUnit { get; set; } = Unit.Percentage; + + /// + /// Gets or sets the zoom level of the . + /// + /// + /// Default value is 14. + /// + [Parameter] + public int Zoom { get; set; } = 14; + + #endregion +} diff --git a/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs b/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs index 579e12171..c6e68b430 100644 --- a/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs +++ b/blazorbootstrap/Components/ScriptLoader/ScriptLoader.razor.cs @@ -24,7 +24,7 @@ public partial class ScriptLoader : BlazorBootstrapComponentBase protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) - await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.scriptLoader.initialize", Id, Async, ScriptId, Source, type, objRef); + await JSRuntime.InvokeVoidAsync("window.blazorBootstrap.scriptLoader.initialize", Id, Async, Defer, ScriptId, Source, type, objRef); await base.OnAfterRenderAsync(firstRender); } @@ -75,6 +75,13 @@ public void OnLoadJS() [Parameter] public bool Async { get; set; } + /// + /// Gets or sets a value indicating whether the script is meant to be executed + /// after the document has been parsed, but before firing DOMContentLoaded event.. + /// + [Parameter] + public bool Defer { get; set; } + /// /// An event that is fired when a script loading error occurs. /// diff --git a/blazorbootstrap/EventArguments/GoogleMapMarkerEventArgs.cs b/blazorbootstrap/EventArguments/GoogleMapMarkerEventArgs.cs new file mode 100644 index 000000000..d9b6830e7 --- /dev/null +++ b/blazorbootstrap/EventArguments/GoogleMapMarkerEventArgs.cs @@ -0,0 +1,22 @@ +namespace BlazorBootstrap; + +public class GoogleMapMarkerEventArgs : EventArgs +{ + #region Constructors + + public GoogleMapMarkerEventArgs(GoogleMapMarker marker) + { + Marker = marker; + } + + #endregion + + #region Properties, Indexers + + /// + /// Gets the elementId. + /// + public GoogleMapMarker Marker { get; } + + #endregion +} diff --git a/blazorbootstrap/Models/Maps/GoogleMapCenter.cs b/blazorbootstrap/Models/Maps/GoogleMapCenter.cs new file mode 100644 index 000000000..f5c49776b --- /dev/null +++ b/blazorbootstrap/Models/Maps/GoogleMapCenter.cs @@ -0,0 +1,24 @@ +namespace BlazorBootstrap; + +public record class GoogleMapCenter +{ + #region Constructors + + public GoogleMapCenter(double latitude, double longitude) + { + Latitude = latitude; + Longitude = longitude; + } + + #endregion + + #region Properties, Indexers + + [JsonPropertyName("lat")] + public double Latitude { get; } + + [JsonPropertyName("lng")] + public double Longitude { get; } + + #endregion +} diff --git a/blazorbootstrap/Models/Maps/GoogleMapMarker.cs b/blazorbootstrap/Models/Maps/GoogleMapMarker.cs new file mode 100644 index 000000000..abd68296a --- /dev/null +++ b/blazorbootstrap/Models/Maps/GoogleMapMarker.cs @@ -0,0 +1,18 @@ +namespace BlazorBootstrap; + +public class GoogleMapMarker +{ + #region Properties, Indexers + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Content { get; set; } + + public PinElement? PinElement { get; set; } + + public GoogleMapMarkerPosition? Position { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Title { get; set; } + + #endregion +} diff --git a/blazorbootstrap/Models/Maps/GoogleMapMarkerPosition.cs b/blazorbootstrap/Models/Maps/GoogleMapMarkerPosition.cs new file mode 100644 index 000000000..934390fe6 --- /dev/null +++ b/blazorbootstrap/Models/Maps/GoogleMapMarkerPosition.cs @@ -0,0 +1,24 @@ +namespace BlazorBootstrap; + +public record class GoogleMapMarkerPosition +{ + #region Constructors + + public GoogleMapMarkerPosition(double latitude, double longitude) + { + Latitude = latitude; + Longitude = longitude; + } + + #endregion + + #region Properties, Indexers + + [JsonPropertyName("lat")] + public double Latitude { get; } + + [JsonPropertyName("lng")] + public double Longitude { get; } + + #endregion +} diff --git a/blazorbootstrap/Models/Maps/PinElement.cs b/blazorbootstrap/Models/Maps/PinElement.cs new file mode 100644 index 000000000..8152835e3 --- /dev/null +++ b/blazorbootstrap/Models/Maps/PinElement.cs @@ -0,0 +1,24 @@ +namespace BlazorBootstrap; + +public class PinElement +{ + #region Properties, Indexers + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Background { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? BorderColor { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public object? Glyph { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? GlyphColor { get; set; } + + public double Scale { get; set; } = 1.0; + + public bool UseIconFonts { get; set; } + + #endregion +} diff --git a/blazorbootstrap/wwwroot/blazor.bootstrap.js b/blazorbootstrap/wwwroot/blazor.bootstrap.js index 4948598a6..078ebcf44 100644 --- a/blazorbootstrap/wwwroot/blazor.bootstrap.js +++ b/blazorbootstrap/wwwroot/blazor.bootstrap.js @@ -392,6 +392,108 @@ window.blazorBootstrap = { bootstrap?.Dropdown?.getOrCreateInstance(dropdownEl)?.update(); } }, + googlemaps: { + addMarker: (elementId, marker, dotNetHelper) => { + let mapInstance = window.blazorBootstrap.googlemaps.get(elementId); + if (mapInstance) { + let map = mapInstance.map; + let clickable = mapInstance.clickable; + let _content; + + if (marker.pinElement) { + let _glyph; + + if (marker.pinElement.useIconFonts) { + const icon = document.createElement("div"); + icon.innerHTML = ``; + _glyph = icon; + } else { + _glyph = marker.pinElement.glyph; + } + + const pin = new google.maps.marker.PinElement({ + background: marker.pinElement.background, + borderColor: marker.pinElement.borderColor, + glyph: _glyph, + glyphColor: marker.pinElement.glyphColor, + scale: marker.pinElement.scale, + }); + _content = pin.element; + } + else if (marker.content) { + _content = document.createElement("div"); + _content.classList.add("bb-google-marker-content"); + _content.innerHTML = marker.content; + } + + const markerEl = new google.maps.marker.AdvancedMarkerElement({ + map, + content: _content, + position: marker.position, + title: marker.title, + gmpClickable: clickable + }); + + window.blazorBootstrap.googlemaps.markerEls[elementId].push(markerEl); + + // add a click listener for each marker, and set up the info window. + if (clickable) { + markerEl.addListener("click", ({ domEvent, latLng }) => { + const { target } = domEvent; + const infoWindow = new google.maps.InfoWindow(); + infoWindow.close(); + infoWindow.setContent(markerEl.title); + infoWindow.open(markerEl.map, markerEl); + dotNetHelper.invokeMethodAsync('OnMarkerClickJS', marker); + }); + } + } + }, + create: (elementId, map, zoom, center, markers, clickable) => { + window.blazorBootstrap.googlemaps.instances[elementId] = { + map: map, + zoom: zoom, + center: center, + markers: markers, + clickable: clickable + }; + }, + get: (elementId) => { + return window.blazorBootstrap.googlemaps.instances[elementId]; + }, + initialize: (elementId, zoom, center, markers, clickable, dotNetHelper) => { + window.blazorBootstrap.googlemaps.markerEls[elementId] = window.blazorBootstrap.googlemaps.markerEls[elementId] ?? [] + + let mapOptions = { center: center, zoom: zoom, mapId: elementId }; + let map = new google.maps.Map(document.getElementById(elementId), mapOptions); + + window.blazorBootstrap.googlemaps.create(elementId, map, zoom, center, markers, clickable); + + if (markers) { + for (const marker of markers) { + window.blazorBootstrap.googlemaps.addMarker(elementId, marker, dotNetHelper); + } + } + }, + instances: {}, + markerEls: {}, + updateMarkers: (elementId, markers, dotNetHelper) => { + let markerEls = window.blazorBootstrap.googlemaps.markerEls[elementId] ?? []; + + // delete the markers + if (markerEls.length > 0) { + for (const markerEl of markerEls) { + markerEl.setMap(null); + } + } + + if (markers) { + for (const marker of markers) { + window.blazorBootstrap.googlemaps.addMarker(elementId, marker, dotNetHelper); + } + } + } + }, grid: { checkOrUnCheckAll: (cssSelector, isChecked) => { let chkEls = document.querySelectorAll(cssSelector); @@ -583,7 +685,7 @@ window.blazorBootstrap = { } }, scriptLoader: { - initialize: (elementId, async, scriptId, source, type, dotNetHelper) => { + initialize: (elementId, async, defer, scriptId, source, type, dotNetHelper) => { let scriptLoaderEl = document.getElementById(elementId); if (source.length === 0) { @@ -595,6 +697,8 @@ window.blazorBootstrap = { scriptEl.async = async; + scriptEl.defer = defer; + if (scriptId != null) scriptEl.id = scriptId;