-
Notifications
You must be signed in to change notification settings - Fork 106
MarkerList for multi markets manipulation
Sample Practical case:
Better place to start is "OnMapAfterInitAsync" event handler
a) Retrieve some entities having "marker role", as bus stop from a own "business service" (or a JSON file, or other things): Stops = gtfsService.Stops[Id] .Values .Where(s => !string.IsNullOrEmpty(s.Code)) .ToList();
Object list need to contains coordinates info and a key to be used to designate univocally a Marker (in that case Stop.Id)
b) Create a new MarkerList using CreateAsync and relative markerOptions (eventually with a title as tooltip for markers, eventually the same or different marker icons):
stopMarkerList = await MarkerList.CreateAsync
(
gtfsMap.JsRuntime,
Stops.ToDictionary(s => s.Id, s => new MarkerOptions
{
Position = new LatLngLiteral(s.Longitude, s.Latitude),
Map = map.InteropObject,
Title = s.Code,
Icon = "/images/stop.png",
Visible = false
})
);
If the marker number is big, is strongly recommended to start with "Visible = false" -> Markers are already on map, but not visible
c) Define when and what markers show, defining map event event handlers:
await map.InteropObject.AddListener("zoom_changed", MapOnBoundsChanged);
await map.InteropObject.AddListener("dragend", MapOnBoundsChanged);
d) Implements MapOnBoundsChanged similar to:
private async void MapOnBoundsChanged()
{
//Use a SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); if you need to be sure to have a "critical section" where only one thread at time can enter
//This is a way to limit the concurrency on markers when user moves "back and forth" many times on map -> however zoom changed and drag end are "good event filter",
//only when user stops to move the map the "drag end" event fires.
await semaphore.WaitAsync();
try
{
int zoom = await gtfsMap.InteropObject.GetZoom();
if (zoom >= 15)
{
LatLngBoundsLiteral bounds = await map.InteropObject.GetBounds();
double minLongitude = Math.Min(bounds.West, bounds.East);
double maxLongitude = Math.Max(bounds.West, bounds.East);
double minLatitude = Math.Min(bounds.North, bounds.South);
double maxLatitude = Math.Max(bounds.North, bounds.South);
//Only id zoom is bigger than a chosen number (f.i. 15) and
//only id our markers are inside Map Bounds
{
//Filter the objects we want to show on map
List<GTFSStop> StopsToShow = Stops.Where(s => (s.Latitude >= minLatitude) && (s.Latitude <= maxLatitude))
.Where(s => (s.Longitude >= minLongitude) && (s.Longitude <= maxLongitude))
.ToList();
//Calc the markers that need to be shown and to be hidden
List<string> MarkersToShow = StopsToShow.Select(s => s.Id).ToList().Except(VisibleStopMarkers).ToList();
List<string> MarkersToHide = VisibleStopMarkers.Except(StopsToShow.Select(s => s.Id).ToList()).ToList();
if (MarkersToShow.Count > 0)
{
//Set visibility at true for all needed markers
*await stopMarkerList.SetVisibles(MarkersToShow.ToDictionary(e => e, e => true));*
//Add only required event listener (important: only when not yet defined)
foreach (string key in MarkersToShow)
{
*Marker marker = stopMarkerList.Markers[key];*
if
(
(!*marker.EventListeners.ContainsKey("click"))* ||
(*marker.EventListeners["click"].Count == 0*)
)
{
*await marker.AddListener("click", async () => { await OnMarkerClick(key); });*
}
}
//Some tested methods usable when needed
*//Dictionary<string, LatLngLiteral> markerPositions = await stopMarkerList.GetPositions(MarkersToShow);
//Dictionary<string,bool> markerClickables = awaitstopMarkerList.GetClickables(MarkersToShow);
//Dictionary<string,string> markerCursors = await stopMarkerList.GetCursors(MarkersToShow);
//Dictionary<string, bool> markerDraggables = await stopMarkerList.GetDraggables(MarkersToShow);
//Dictionary<string,string> markerLabels = await stopMarkerList.GetLabels(MarkersToShow);
//Dictionary<string, string> markerTitles = await stopMarkerList.GetTitles(MarkersToShow);
//Dictionary<string, bool> markerVisibles = await stopMarkerList.GetVisibles(MarkersToShow);
//Dictionary<string, int> markerZIndexes = await stopMarkerList.GetZIndexes(MarkersToShow);*
//Set visibility to false to markers to be hidden
if (MarkersToHide.Count > 0)
{
*await stopMarkerList.SetVisibles(MarkersToHide.ToDictionary(e=> e, e => false));*
}
VisibleStopMarkers = StopsToShow.Select(s => s.Id).ToList();
}
}
}
else
{
//Zoom is too low? Hide all markers (not usable contents on map due to overcrowding when a lot of markers are shown)
{
*await stopMarkerList.SetVisibles(VisibleStopMarkers.ToDictionary(e=> e, e => false));*
//Don't forget to clear the list of visible markers!
VisibleStopMarkers.Clear();
}
}
}
finally
{
//Don't forget to release the semaphore, otherwise no other threads can be enter in the "critical section"
semaphore.Release();
}
}