Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#29, #30, 32 Updates to map properties, fixed memory leak. #33

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions BlazorLeaflet/BlazorLeaflet.Samples/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
<button class="btn btn-primary mb-2" @onclick="FindCity">Search</button>
<button class="btn btn-primary mb-2" @onclick="ZoomMap">Zoom</button>
<button class="btn btn-primary mb-2" @onclick="PanToNY">Pan to New York</button>
<button class="btn btn-primary mb-2" @onclick="SetToNY">Set center at New York</button>
</div>

<div style="height: 500px; width: 500px;">
<LeafletMap Map="_map" />
</div>
<p>Map bounds: @_map.Bounds?.ToString()</p>


@code
{
Expand Down Expand Up @@ -67,6 +70,7 @@
};
_map.AddLayer(_circle);
};
_map.OnBoundsChanged += (s, e) => this.StateHasChanged();
}

private LatLng _startAt = new LatLng(47.5574007f, 16.3918687f);
Expand Down Expand Up @@ -102,12 +106,18 @@

private void ZoomMap()
{
_map.FitBounds(new PointF(45.943f, 24.967f), new PointF(46.943f, 25.967f), maxZoom: 5f);
}

private void PanToNY()
{
_map.PanTo(new PointF(40.713185f, -74.0072333f), animate: true, duration: 10f);
_map.FitBounds(new PointF(45.943f, 24.967f), new PointF(46.943f, 25.967f), maxZoom: 5f);
}

private void PanToNY()
{
_map.PanTo(new PointF(40.713185f, -74.0072333f), animate: true, duration: 10f);
}

private void SetToNY()
{
_map.Center = new LatLng(new PointF(40.713185f, -74.0072333f));
_map.Zoom = 15;
}

}
78 changes: 62 additions & 16 deletions BlazorLeaflet/BlazorLeaflet/LeafletInterops.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BlazorLeaflet.Models;
using BlazorLeaflet.Models;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading.Tasks;
using Rectangle = BlazorLeaflet.Models.Rectangle;
Expand All @@ -10,29 +11,56 @@ namespace BlazorLeaflet
public static class LeafletInterops
{

private static Dictionary<string, (IDisposable, string, Layer)> LayerReferences { get; }
= new Dictionary<string, (IDisposable, string, Layer)>();

private static readonly string _BaseObjectContainer = "window.leafletBlazor";

public static ValueTask Create(IJSRuntime jsRuntime, Map map) =>
jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.create", map, DotNetObjectReference.Create(map));

public static ValueTask AddLayer(IJSRuntime jsRuntime, string mapId, Layer layer) =>
layer switch
private static DotNetObjectReference<T> CreateLayerReference<T>(string mapId, T layer) where T : Layer
{
var result = DotNetObjectReference.Create(layer);
LayerReferences.Add(layer.Id, (result, mapId, layer));
return result;
}

private static void DisposeLayerReference(string layerId)
{
if (LayerReferences.TryGetValue(layerId, out var value))
{
value.Item1.Dispose();
LayerReferences.Remove(layerId);
}
}

public static ValueTask AddLayer(IJSRuntime jsRuntime, string mapId, Layer layer)
{
return layer switch
{
TileLayer tileLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addTilelayer", mapId, tileLayer, DotNetObjectReference.Create(tileLayer)),
MbTilesLayer mbTilesLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addMbTilesLayer", mapId, mbTilesLayer, DotNetObjectReference.Create(mbTilesLayer)),
ShapefileLayer shapefileLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addShapefileLayer", mapId, shapefileLayer, DotNetObjectReference.Create(shapefileLayer)),
Marker marker => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addMarker", mapId, marker, DotNetObjectReference.Create(marker)),
Rectangle rectangle => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addRectangle", mapId, rectangle, DotNetObjectReference.Create(rectangle)),
Circle circle => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addCircle", mapId, circle, DotNetObjectReference.Create(circle)),
Polygon polygon => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addPolygon", mapId, polygon, DotNetObjectReference.Create(polygon)),
Polyline polyline => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addPolyline", mapId, polyline, DotNetObjectReference.Create(polyline)),
ImageLayer image => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addImageLayer", mapId, image, DotNetObjectReference.Create(image)),
GeoJsonDataLayer geo => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addGeoJsonLayer", mapId, geo, DotNetObjectReference.Create(geo)),
TileLayer tileLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addTilelayer", mapId, tileLayer, CreateLayerReference(mapId, tileLayer)),
MbTilesLayer mbTilesLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addMbTilesLayer", mapId, mbTilesLayer, CreateLayerReference(mapId, mbTilesLayer)),
ShapefileLayer shapefileLayer => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addShapefileLayer", mapId, shapefileLayer, CreateLayerReference(mapId, shapefileLayer)),
Marker marker => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addMarker", mapId, marker, CreateLayerReference(mapId, marker)),
Rectangle rectangle => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addRectangle", mapId, rectangle, CreateLayerReference(mapId, rectangle)),
Circle circle => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addCircle", mapId, circle, CreateLayerReference(mapId, circle)),
Polygon polygon => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addPolygon", mapId, polygon, CreateLayerReference(mapId, polygon)),
Polyline polyline => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addPolyline", mapId, polyline, CreateLayerReference(mapId, polyline)),
ImageLayer image => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addImageLayer", mapId, image, CreateLayerReference(mapId, image)),
GeoJsonDataLayer geo => jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.addGeoJsonLayer", mapId, geo, CreateLayerReference(mapId, geo)),
_ => throw new NotImplementedException($"The layer {typeof(Layer).Name} has not been implemented."),
};
};
}

public static ValueTask RemoveLayer(IJSRuntime jsRuntime, string mapId, string layerId) =>
jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.removeLayer", mapId, layerId);
public static async ValueTask RemoveLayer(IJSRuntime jsRuntime, string mapId, string layerId)
{
await jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.removeLayer", mapId, layerId);
DisposeLayerReference(layerId);
}

public static ValueTask SetMarkerIcon(IJSRuntime jsRuntime, string mapId, string layerId, Icon icon)
=> jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.setMarkerIcon", mapId, layerId, icon);

public static ValueTask UpdatePopupContent(IJSRuntime jsRuntime, string mapId, Layer layer) =>
jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.updatePopupContent", mapId, layer.Id, layer.Popup?.Content);
Expand Down Expand Up @@ -61,5 +89,23 @@ layer switch

public static ValueTask<float> GetZoom(IJSRuntime jsRuntime, string mapId) =>
jsRuntime.InvokeAsync<float>($"{_BaseObjectContainer}.getZoom", mapId);

private class _Bounds
{
public LatLng _southWest { get; set; }
public LatLng _northEast { get; set; }
AlexKven marked this conversation as resolved.
Show resolved Hide resolved

public Bounds AsBounds() => new Bounds(_southWest, _northEast);
}

public static async Task<Bounds> GetBounds(IJSRuntime jsRuntime, string mapId)
{
return (await jsRuntime.InvokeAsync<_Bounds>($"{_BaseObjectContainer}.getBounds", mapId)).AsBounds();
}

public static async Task SetZoom(IJSRuntime jsRuntime, string mapId, float zoomLevel)
{
await jsRuntime.InvokeVoidAsync($"{_BaseObjectContainer}.setZoom", mapId, zoomLevel);
}
}
}
101 changes: 94 additions & 7 deletions BlazorLeaflet/BlazorLeaflet/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,44 @@ namespace BlazorLeaflet
{
public class Map
{
private LatLng _Center = new LatLng();
/// <summary>
/// Initial geographic center of the map
/// Geographic center of the map
/// </summary>
public LatLng Center { get; set; } = new LatLng();
///
public LatLng Center
{
get => _Center;
set
{
_Center = value;
if (_isInitialized)
RunTaskInBackground(async () => await LeafletInterops.PanTo(
_jsRuntime, Id, value.ToPointF(), false, 0, 0, false));
}
}

private float _Zoom;
/// <summary>
/// Initial map zoom level
/// Map zoom level
/// </summary>
public float Zoom { get; set; }

public float Zoom
{
get => _Zoom;
set
{
_Zoom = value;
if (_isInitialized)
RunTaskInBackground(async () => await LeafletInterops.SetZoom(
_jsRuntime, Id, value));
}
}

/// <summary>
/// Map bounds
/// </summary>
public Bounds Bounds { get; private set; }

/// <summary>
/// Minimum zoom level of the map. If not specified and at least one
/// GridLayer or TileLayer is in the map, the lowest of their minZoom
Expand Down Expand Up @@ -74,6 +102,19 @@ public void RaiseOnInitialized()
{
_isInitialized = true;
OnInitialized?.Invoke();
RunTaskInBackground(UpdateBounds);
}

private async void RunTaskInBackground(Func<Task> task)
{
try
{
await task();
}
catch (Exception ex)
{
NotifyBackgroundExceptionOccurred(ex);
}
}

/// <summary>
Expand Down Expand Up @@ -171,6 +212,26 @@ public void PanTo(PointF position, bool animate = false, float duration = 0.25f,

public async Task<LatLng> GetCenter() => await LeafletInterops.GetCenter(_jsRuntime, Id);
public async Task<float> GetZoom() => await LeafletInterops.GetZoom(_jsRuntime, Id);
public async Task<Bounds> GetBounds() => await LeafletInterops.GetBounds(_jsRuntime, Id);

private async Task UpdateZoom()
{
_Zoom = await GetZoom();
await UpdateBounds();
}

private async Task UpdateCenter()
{

_Center = await GetCenter();
await UpdateBounds();
}

private async Task UpdateBounds()
{
Bounds = await GetBounds();
OnBoundsChanged?.Invoke(this, new EventArgs());
}

#region events

Expand Down Expand Up @@ -215,11 +276,33 @@ public void PanTo(PointF position, bool animate = false, float duration = 0.25f,

public event MapEventHandler OnZoomEnd;
[JSInvokable]
public void NotifyZoomEnd(Event e) => OnZoomEnd?.Invoke(this, e);
public async void NotifyZoomEnd(Event e)
{
try
{
await UpdateZoom();
}
finally
{
OnZoomEnd?.Invoke(this, e);
}
}

public event MapEventHandler OnMoveEnd;
[JSInvokable]
public void NotifyMoveEnd(Event e) => OnMoveEnd?.Invoke(this, e);
public async void NotifyMoveEnd(Event e)
{
try
{
await UpdateCenter();
}
finally
{
OnMoveEnd?.Invoke(this, e);
}
}

public event EventHandler OnBoundsChanged;

public event MouseEventHandler OnMouseMove;
[JSInvokable]
Expand All @@ -241,6 +324,10 @@ public void PanTo(PointF position, bool animate = false, float duration = 0.25f,
[JSInvokable]
public void NotifyPreClick(MouseEvent eventArgs) => OnPreClick?.Invoke(this, eventArgs);

public event EventHandler<Exception> BackgroundExceptionOccurred;
private void NotifyBackgroundExceptionOccurred(Exception exception) =>
BackgroundExceptionOccurred?.Invoke(this, exception);

#endregion events

#region InteractiveLayerEvents
Expand Down
26 changes: 26 additions & 0 deletions BlazorLeaflet/BlazorLeaflet/Models/Bounds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;

namespace BlazorLeaflet.Models
{
public class Bounds
{
[DataMember(Name = "_northEast")]
public LatLng NorthEast { get; set; }

[DataMember(Name = "_southWest")]
public LatLng SouthWest { get; set; }

public Bounds() { }
public Bounds(LatLng southWest, LatLng northEast)
{
NorthEast = northEast;
SouthWest = southWest;
}

public override string ToString() =>
$"NE: {NorthEast.Lat} N, {NorthEast.Lng} E; SW: {SouthWest.Lat} N, {SouthWest.Lng} E";
}
}
8 changes: 7 additions & 1 deletion BlazorLeaflet/BlazorLeaflet/wwwroot/leafletBlazorInterops.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
maps = {};
maps = {};
layers = {};

window.leafletBlazor = {
Expand Down Expand Up @@ -206,6 +206,12 @@ window.leafletBlazor = {
},
getZoom: function (mapId) {
return maps[mapId].getZoom();
},
getBounds: function (mapId) {
return maps[mapId].getBounds();
},
setZoom: function (mapId, zoomLevel) {
maps[mapId].setZoom(zoomLevel);
}
};

Expand Down