Skip to content

Commit

Permalink
Add Support for PinElement (AdvancedMarkerElement Customization) #336
Browse files Browse the repository at this point in the history
  • Loading branch information
valentasm committed Jun 26, 2024
1 parent 1137cf3 commit 7f21f1d
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 89 deletions.
3 changes: 2 additions & 1 deletion GoogleMapsComponents/Maps/AdvancedMarkerViewOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using OneOf;
using System;
using System.Text.Json.Serialization;

Expand All @@ -24,7 +25,7 @@ public class AdvancedMarkerElementOptions : ListableEntityOptionsBase
/// 2023-10-29 Currently only html content is supported
/// Svg, images url could not work
/// </summary>
public string? Content { get; set; }
public OneOf<string, PinElement> Content { get; set; }

/// <summary>
/// If true, the AdvancedMarkerElement can be dragged.
Expand Down
2 changes: 0 additions & 2 deletions GoogleMapsComponents/Maps/ListableEntityBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ public virtual Task<Map> GetMap()
public virtual async Task SetMap(Map? map)
{
await _jsObjectRef.InvokeAsync("setMap", map);

//_map = map;
}

public Task InvokeAsync(string functionName, params object[] args)
Expand Down
37 changes: 5 additions & 32 deletions GoogleMapsComponents/Maps/PinElement.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using Microsoft.JSInterop;
using System;
using System.Threading.Tasks;

namespace GoogleMapsComponents.Maps;
namespace GoogleMapsComponents.Maps;

/// <summary>
/// A PinElement represents a DOM element that consists of a shape and a glyph. The shape has the same balloon style as seen in the default AdvancedMarkerElement. The glyph is an optional DOM element displayed in the balloon shape. A PinElement may have a different aspect ratio depending on its PinElement.scale.
Expand All @@ -12,35 +8,12 @@ public class PinElement// : EventEntityBase
{
public string? Background { get; set; }
public string? BorderColor { get; set; }
// private ElementReference Element { get; set; }

public PinElement() : base()
{

}
public static async Task<PinElement> CreateAsync(IJSRuntime jsRuntime, PinElementOptions? opts = null)
{
var id = Guid.NewGuid();
var jsObjectRef = new JsObjectRef(jsRuntime, id);
var result = await jsObjectRef.InvokeAsync<PinElement>("google.maps.marker.PinElement", opts);
//var jsObjectRef = await JsObjectRef.CreateAsync(jsRuntime, "google.maps.marker.PinElement", opts);
//var obj = new PinElement(jsObjectRef);
return result;
}


protected PinElement(JsObjectRef jsObjectRef) : base()
{
}

public string? Glyph { get; set; }
public string? GlyphColor { get; set; }
public int? Scale { get; set; }

public async Task<string> GetContent()
public PinElement()
{
//_jsObjectRef.JSRuntime.
//await _jsObjectRef.InvokeAsync("element");
//var ss = element.ToString();

//return element.ToString();
return "";
}
}
59 changes: 43 additions & 16 deletions GoogleMapsComponents/wwwroot/js/objectManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,39 @@
}
};

//It is impossible to pass to pass HTMLElement from blazor to google maps
//Due to this we need to create it in js side.
function getAdvancedMarkerElementContent(functionName, content) {
if (functionName == "google.maps.marker.AdvancedMarkerView" || functionName == "google.maps.marker.AdvancedMarkerElement") {
if (content) {
var isPinElement = content.dotnetTypeName === "GoogleMapsComponents.Maps.PinElement";

if (isPinElement) {
let pin = new google.maps.marker.PinElement({
background: content.background,
borderColor: content.borderColor,
glyphColor: content.glyphColor,
scale: content.scale,
});

let glyph = content.glyph;
if (glyph) {
pin.glyph = glyph.startsWith("http") ? new URL(glyph) : glyph;
}

return pin.element;
}
else {
let template = document.createElement('template');
template.innerHTML = content.trim();
return template.content.firstChild;
}
}
}

return null;
};

return {
objectManager: {
get mapObjects() { return mapObjects; },
Expand All @@ -351,17 +384,13 @@
mapObjects = mapObjects || [];

let args2 = args.slice(2).map(arg => tryParseJson(arg));
//console.log(args2);

let functionName = args[1];
if (functionName == "google.maps.marker.AdvancedMarkerView" || functionName == "google.maps.marker.AdvancedMarkerElement") {
var content = args2[0].content;
if (content != null && content !== undefined) {
var template = document.createElement('template');
content = content.trim();
template.innerHTML = content;
args2[0].content = template.content.firstChild;
}
let advancedMarkerElementContent = getAdvancedMarkerElementContent(functionName, args2.length > 0 ? args2[0].content : null);
if (advancedMarkerElementContent !== null) {
args2[0].content = advancedMarkerElementContent;
}

let constructor = stringToFunction(functionName);
let obj = new constructor(...args2);
let guid = args[0];
Expand Down Expand Up @@ -389,13 +418,9 @@

for (var i = 0, len = args2.length; i < len; i++) {
var constructorArgs = args2[i];
if (functionName == "google.maps.marker.AdvancedMarkerView" || functionName == "google.maps.marker.AdvancedMarkerElement") {
if(constructorArgs.content != null && constructorArgs.content !== undefined) {
var template = document.createElement('template');
constructorArgs.content = constructorArgs.content.trim();
template.innerHTML = constructorArgs.content;
constructorArgs.content = template.content.firstChild;
}
let advancedMarkerElementContent = getAdvancedMarkerElementContent(functionName, constructorArgs.content);
if (advancedMarkerElementContent !== null) {
constructorArgs.content = advancedMarkerElementContent;
}

let obj = new constructor(constructorArgs);
Expand All @@ -408,6 +433,8 @@
}
},



addObject: function (obj, guid) {
if (guid === null || typeof guid === "undefined") {
guid = uuidv4();
Expand Down
84 changes: 61 additions & 23 deletions ServerSideDemo/Pages/MapAdvancedMarkerViewPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
<button @onclick="FitBounds">Fit to advanced markers</button>

<MapEventList Events="@_events"></MapEventList>
<div style="color:red" @ref="@_div">Football</div>

@code {

private ElementReference _div;
private GoogleMap _map1 = null!;
private MapOptions _mapOptions = new MapOptions()
private int _counter;
const string Svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"56\" height=\"56\" viewBox=\"0 0 56 56\" fill=\"none\">\r\n <rect width=\"56\" height=\"56\" rx=\"28\" fill=\"#7837FF\"></rect>\r\n <path d=\"M46.0675 22.1319L44.0601 22.7843\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M11.9402 33.2201L9.93262 33.8723\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M27.9999 47.0046V44.8933\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M27.9999 9V11.1113\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M39.1583 43.3597L37.9186 41.6532\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M16.8419 12.6442L18.0816 14.3506\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M9.93262 22.1319L11.9402 22.7843\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M46.0676 33.8724L44.0601 33.2201\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M39.1583 12.6442L37.9186 14.3506\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M16.8419 43.3597L18.0816 41.6532\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M28 39L26.8725 37.9904C24.9292 36.226 23.325 34.7026 22.06 33.4202C20.795 32.1378 19.7867 30.9918 19.035 29.9823C18.2833 28.9727 17.7562 28.0587 17.4537 27.2401C17.1512 26.4216 17 25.5939 17 24.7572C17 23.1201 17.5546 21.7513 18.6638 20.6508C19.7729 19.5502 21.1433 19 22.775 19C23.82 19 24.7871 19.2456 25.6762 19.7367C26.5654 20.2278 27.34 20.9372 28 21.8649C28.77 20.8827 29.5858 20.1596 30.4475 19.6958C31.3092 19.2319 32.235 19 33.225 19C34.8567 19 36.2271 19.5502 37.3362 20.6508C38.4454 21.7513 39 23.1201 39 24.7572C39 25.5939 38.8488 26.4216 38.5463 27.2401C38.2438 28.0587 37.7167 28.9727 36.965 29.9823C36.2133 30.9918 35.205 32.1378 33.94 33.4202C32.675 34.7026 31.0708 36.226 29.1275 37.9904L28 39Z\" fill=\"#FF7878\"></path>\r\n</svg>";
private readonly MapOptions _mapOptions = new MapOptions()
{
Zoom = 13,
Center = new LatLngLiteral()
Expand All @@ -51,24 +51,23 @@

private async Task AddMarker()
{
const string svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"56\" height=\"56\" viewBox=\"0 0 56 56\" fill=\"none\">\r\n <rect width=\"56\" height=\"56\" rx=\"28\" fill=\"#7837FF\"></rect>\r\n <path d=\"M46.0675 22.1319L44.0601 22.7843\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M11.9402 33.2201L9.93262 33.8723\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M27.9999 47.0046V44.8933\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M27.9999 9V11.1113\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M39.1583 43.3597L37.9186 41.6532\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M16.8419 12.6442L18.0816 14.3506\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M9.93262 22.1319L11.9402 22.7843\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M46.0676 33.8724L44.0601 33.2201\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M39.1583 12.6442L37.9186 14.3506\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M16.8419 43.3597L18.0816 41.6532\" stroke=\"white\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\r\n <path d=\"M28 39L26.8725 37.9904C24.9292 36.226 23.325 34.7026 22.06 33.4202C20.795 32.1378 19.7867 30.9918 19.035 29.9823C18.2833 28.9727 17.7562 28.0587 17.4537 27.2401C17.1512 26.4216 17 25.5939 17 24.7572C17 23.1201 17.5546 21.7513 18.6638 20.6508C19.7729 19.5502 21.1433 19 22.775 19C23.82 19 24.7871 19.2456 25.6762 19.7367C26.5654 20.2278 27.34 20.9372 28 21.8649C28.77 20.8827 29.5858 20.1596 30.4475 19.6958C31.3092 19.2319 32.235 19 33.225 19C34.8567 19 36.2271 19.5502 37.3362 20.6508C38.4454 21.7513 39 23.1201 39 24.7572C39 25.5939 38.8488 26.4216 38.5463 27.2401C38.2438 28.0587 37.7167 28.9727 36.965 29.9823C36.2133 30.9918 35.205 32.1378 33.94 33.4202C32.675 34.7026 31.0708 36.226 29.1275 37.9904L28 39Z\" fill=\"#FF7878\"></path>\r\n</svg>";
var mapCenter = await _map1.InteropObject.GetCenter();

var marker = await AdvancedMarkerElement.CreateAsync(_map1.JsRuntime, new AdvancedMarkerElementOptions()
{
Position = mapCenter,
Map = _map1.InteropObject,
Content =svg,
Content = Svg
});

_markers.Push(marker);
await _bounds.Extend(mapCenter);

await marker.AddListener<MouseEvent>("click", async e =>
await marker.AddListener<MouseEvent>("click", e =>
{
_events.Add($"Clicked {e.LatLng.Lat} {e.LatLng.Lng}");
StateHasChanged();
await e.Stop();
e.Stop();
});
}

Expand Down Expand Up @@ -198,24 +197,63 @@

private async Task AddMarkerWithPinElement()
{
//Some examples of pin elements
//https://developers.google.com/maps/documentation/javascript/advanced-markers/graphic-markers#javascript
var mapCenter = await _map1.InteropObject.GetCenter();
var pinElement = await PinElement.CreateAsync(_map1.JsRuntime, new PinElementOptions()
{
Background= "#FBBC04",
BorderColor = "#137333",
});
PinElement? pinElement;
_counter++;
const string constantImageSource = "https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png";

// var background = await pinElement.Getbackground();
//var content = await pinElement.GetContent();
// var marker = await AdvancedMarkerElement.CreateAsync(_map1.JsRuntime, new AdvancedMarkerElementOptions()
// {
// Position = mapCenter,
// Map = _map1.InteropObject,
// Content = content,
// });
AdvancedMarkerElement marker;
var actionNr = _counter % 3;
if (actionNr == 0)
{
pinElement = new PinElement()
{
BorderColor = "red",
Background= "blue",
Scale = 2
};

marker = await AdvancedMarkerElement.CreateAsync(_map1.JsRuntime, new AdvancedMarkerElementOptions()
{
Position = mapCenter,
Map = _map1.InteropObject,
Content = pinElement
});
}
else if (actionNr == 1)
{
pinElement = new PinElement()
{
Glyph = constantImageSource,
Background = "green",
Scale = 2
};

marker = await AdvancedMarkerElement.CreateAsync(_map1.JsRuntime, new AdvancedMarkerElementOptions()
{
Position = mapCenter,
Map = _map1.InteropObject,
Content = pinElement

});
}
else
{
marker = await AdvancedMarkerElement.CreateAsync(_map1.JsRuntime, new AdvancedMarkerElementOptions()
{
Position = mapCenter,
Map = _map1.InteropObject,
Content = Svg
});
}

// _markers.Push(marker);
// await _bounds.Extend(mapCenter);
await marker.AddListener<MouseEvent>("click", e =>
{
_events.Add($"Clicked Pin Marker {e.LatLng.Lat} {e.LatLng.Lng}");
StateHasChanged();
e.Stop();
});
}
}
2 changes: 1 addition & 1 deletion ServerSideDemo/Pages/MapCircleListPage.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private async void CreateBunchOfCircles()

private async Task RefreshCircleList()
{
_circleList = await CircleList.SyncAsync(_circleList, _map.JsRuntime, _circleOptionsByRef, async (ev, sKey, entity) =>
_circleList = await CircleList.SyncAsync(_circleList, _map.JsRuntime, _circleOptionsByRef, async (_, sKey, _) =>
{
// Circle has been clicked --> delete it.
_circleOptionsByRef.Remove(sKey);
Expand Down
16 changes: 6 additions & 10 deletions ServerSideDemo/Pages/MapMarker.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public partial class MapMarker
private MapEventList _eventList;

private LatLngBounds _bounds;
private MarkerClustering _markerClustering;
private MarkerClustering? _markerClustering;
public int ZIndex { get; set; } = 0;

[Inject]
Expand Down Expand Up @@ -78,9 +78,12 @@ private async Task InvokeClustering()
}
await _markerClustering.AddMarkers(markers);

LatLngBoundsLiteral boundsLiteral = new LatLngBoundsLiteral(new LatLngLiteral() { Lat = coordinates.First().Lat, Lng = coordinates.First().Lng });
var boundsLiteral = new LatLngBoundsLiteral(new LatLngLiteral() { Lat = coordinates.First().Lat, Lng = coordinates.First().Lng });
foreach (var literal in coordinates)
{
LatLngBoundsLiteral.CreateOrExtend(ref boundsLiteral, literal);
}

await _map1.InteropObject.FitBounds(boundsLiteral, OneOf.OneOf<int, GoogleMapsComponents.Maps.Coordinates.Padding>.FromT0(1));

}
Expand Down Expand Up @@ -183,7 +186,7 @@ private static List<LatLngLiteral> GetClusterCoordinates()
};
}

private async Task<IEnumerable<Marker>> GetMarkers(IEnumerable<LatLngLiteral> coords, Map map)
private async Task<IEnumerable<Marker>> GetMarkers(ICollection<LatLngLiteral> coords, Map map)
{
var result = new List<Marker>(coords.Count());
var index = 1;
Expand Down Expand Up @@ -219,13 +222,6 @@ private async Task AddMarkerStyled()
Position = mapCenter,
Map = _map1.InteropObject,
ZIndex = ZIndex,
//Icon = new Symbol()
//{
// Path = "M10.453 14.016l6.563-6.609-1.406-1.406-5.156 5.203-2.063-2.109-1.406 1.406zM12 2.016q2.906 0 4.945 2.039t2.039 4.945q0 1.453-0.727 3.328t-1.758 3.516-2.039 3.070-1.711 2.273l-0.75 0.797q-0.281-0.328-0.75-0.867t-1.688-2.156-2.133-3.141-1.664-3.445-0.75-3.375q0-2.906 2.039-4.945t4.945-2.039z"
//},
//Note that font properties are overriden in class
//Please be cautious about versioning issues and some issues when using other tools
//https://developers.google.com/maps/documentation/javascript/reference/marker#MarkerLabel.className
Label = new MarkerLabel
{
Text = $"Test {_markers.Count()}",
Expand Down
10 changes: 7 additions & 3 deletions ServerSideDemo/Pages/MapPolyline.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@page "/mapPolyline"
@using GoogleMapsComponents
@using GoogleMapsComponents.Maps
@inject IJSRuntime JsRuntime

<h1>Polylines</h1>

Expand Down Expand Up @@ -32,16 +33,16 @@

private List<LatLngLiteral> _path = new List<LatLngLiteral>();

private List<Polyline> _polylines = new List<Polyline>();
private readonly List<Polyline> _polylines = new List<Polyline>();
private Polyline? _polyline;

private List<Polygon> _polygons = new List<Polygon>();
private readonly List<Polygon> _polygons = new List<Polygon>();
private Polygon? _polygon;

private Rectangle? _rectangle;
private Circle? _circle;

private List<String> _events = new List<String>();
private List<string> _events = new List<string>();

protected override void OnInitialized()
{
Expand All @@ -60,6 +61,9 @@
private async Task OnAfterMapInit()
{
await _map1.InteropObject.AddListener<MouseEvent>("click", async (e) => await OnClick(e));

IJSObjectReference serverSideScripts = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "/js/serverSideScripts.js");
await serverSideScripts.InvokeVoidAsync("initServerSideScript");
}

private async Task StartDrawingPolyline()
Expand Down
2 changes: 1 addition & 1 deletion ServerSideDemo/Pages/MapsLegendPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@

private async Task<Map> CreateMap(ElementReference elementReference)
{

var mapOptions = new MapOptions()
{
Zoom = 13,
Expand All @@ -55,6 +54,7 @@
},
MapTypeId = MapTypeId.Roadmap
};

return await Map.CreateAsync(JsRuntime, elementReference, mapOptions);
}

Expand Down
Loading

0 comments on commit 7f21f1d

Please sign in to comment.