diff --git a/BlazorLeaflet/BlazorLeaflet.Samples/Pages/GeoJson.razor b/BlazorLeaflet/BlazorLeaflet.Samples/Pages/GeoJson.razor new file mode 100644 index 0000000..d105899 --- /dev/null +++ b/BlazorLeaflet/BlazorLeaflet.Samples/Pages/GeoJson.razor @@ -0,0 +1,122 @@ +@page "/geojson" + +@using BlazorLeaflet.Models +@using BlazorLeaflet.Models.Events +@inject IJSRuntime jsRuntime + +

Blazor Leaflet

+ +

+ This page demos GeoJSON layers. +

+ +

+ By default, each point in a GeoJSON layer is just a normal marker. Instead, + you can optionally set PointToLayer to a method that + customizes the layer each point corresponds to. Currently, only markers are + supported. +

+ +
+ +
+ +@code +{ + private Map _map; + private LatLng _markerLatLng = new LatLng { Lat = 18, Lng = -76 }; + + protected override void OnInitialized() + { + var badEuropeMap = @" +{ + ""type"": ""FeatureCollection"", + ""features"": [ + { + ""type"": ""Feature"", + ""properties"": { + ""country"": ""Cuba"" + }, + ""geometry"": { + ""type"": ""Point"", + ""coordinates"": [ + -82.44140625, + 22.917922936146045 + ] + } + }, + { + ""type"": ""Feature"", + ""properties"": { + ""country"": ""USA"" + }, + ""geometry"": { + ""type"": ""Point"", + ""coordinates"": [ + -80.244140625, + 25.720735134412106 + ] + } + }, + { + ""type"": ""Feature"", + ""properties"": { + ""country"": ""Venezuela"" + }, + ""geometry"": { + ""type"": ""Point"", + ""coordinates"": [ + -68.9501953125, + 12.211180191503997 + ] + } + } + ] +} +"; + + var dataLayer = new GeoJsonDataLayer + { + GeoJsonData = badEuropeMap + }; + + dataLayer.PointToLayer = new Func((feature, latLng) => + { + return new Marker(latLng) + { + Icon = new Icon + { + Size = new System.Drawing.Size(24, 24), + Url = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Run.svg/200px-Run.svg.png", + ClassName = "map-icon", + }, + Tooltip = new Tooltip + { + Content = "This is a tooltip", + }, + Popup = new Popup + { + Content = "This is a popup", + }, + Title = "This is the title attribute" + }; + }); + + _map = new Map(jsRuntime) + { + Center = _markerLatLng, + Zoom = 4.8f + }; + + _map.OnInitialized += () => + { + _map.AddLayer(new TileLayer + { + UrlTemplate = "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png", + Attribution = "© OpenStreetMap contributors", + }); + + _map.AddLayer(dataLayer); + }; + } +} diff --git a/BlazorLeaflet/BlazorLeaflet.Samples/Shared/NavMenu.razor b/BlazorLeaflet/BlazorLeaflet.Samples/Shared/NavMenu.razor index 03e741c..15e472d 100644 --- a/BlazorLeaflet/BlazorLeaflet.Samples/Shared/NavMenu.razor +++ b/BlazorLeaflet/BlazorLeaflet.Samples/Shared/NavMenu.razor @@ -11,12 +11,15 @@ Home - - Shapes - Custom Controls + + GeoJSON Data + + + Shapes + diff --git a/BlazorLeaflet/BlazorLeaflet/Models/GeoJsonDataLayer.cs b/BlazorLeaflet/BlazorLeaflet/Models/GeoJsonDataLayer.cs index b729233..3237cb1 100644 --- a/BlazorLeaflet/BlazorLeaflet/Models/GeoJsonDataLayer.cs +++ b/BlazorLeaflet/BlazorLeaflet/Models/GeoJsonDataLayer.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.JSInterop; +using System; using System.Collections.Generic; using System.Text; @@ -7,5 +8,27 @@ namespace BlazorLeaflet.Models public class GeoJsonDataLayer : InteractiveLayer { public string GeoJsonData { get; set; } + + public bool HasPointToLayerFunc => PointToLayer != null; + + [System.Text.Json.Serialization.JsonIgnore] + public Func PointToLayer { get; set; } + + [JSInvokable] + public object CallPointToLayer(GeoJsonFeature feature, LatLng latLng) + { + var layer = PointToLayer(feature, latLng); + + if (!(layer is Marker)) + throw new NotSupportedException("Only Marker layers are currently implemented for PointToLayer."); + + return new { Layer = layer, Ref = DotNetObjectReference.Create(layer) }; + } + } + + public class GeoJsonFeature + { + public object Geometry { get; set; } + public Dictionary Properties { get; set; } } } diff --git a/BlazorLeaflet/BlazorLeaflet/wwwroot/leafletBlazorInterops.js b/BlazorLeaflet/BlazorLeaflet/wwwroot/leafletBlazorInterops.js index 7b57cde..ada31a5 100644 --- a/BlazorLeaflet/BlazorLeaflet/wwwroot/leafletBlazorInterops.js +++ b/BlazorLeaflet/BlazorLeaflet/wwwroot/leafletBlazorInterops.js @@ -156,6 +156,50 @@ window.leafletBlazor = { } }; + if (geodata.hasPointToLayerFunc) { + options.pointToLayer = function pointToLayer(geoJsonPoint, latlng) { + var _mapId = mapId; + + // we need to first pass leaflet an empty layer group, + // then asynchronously add our actual layer to it + + var emptyGroup = L.layerGroup(); + + objectReference.invokeMethodAsync("CallPointToLayer", geoJsonPoint, latlng) + .then(function (result) { + const marker = result.layer; + + var options = { + ...createInteractiveLayer(marker), + keyboard: marker.isKeyboardAccessible, + title: marker.title, + alt: marker.alt, + zIndexOffset: marker.zIndexOffset, + opacity: marker.opacity, + riseOnHover: marker.riseOnHover, + riseOffset: marker.riseOffset, + pane: marker.pane, + bubblingMouseEvents: marker.isBubblingMouseEvents, + draggable: marker.draggable, + autoPan: marker.useAutopan, + autoPanPadding: marker.autoPanPadding, + autoPanSpeed: marker.autoPanSpeed + }; + + if (marker.icon !== null) { + options.icon = createIcon(marker.icon); + } + const mkr = L.marker(marker.position, options); + connectMarkerEvents(mkr, objectReference); + setTooltipAndPopupIfDefined(marker, mkr); + + mkr.addTo(emptyGroup); + }); + + return emptyGroup; + }; + } + const geoJsonLayer = L.geoJson(geoDataObject, options); addLayer(mapId, geoJsonLayer, geodata.id); },