How to group the markers based on zoom level in the imagery layer of the SfMaps control
This article describes how to display individual markers in a corresponding location at high zoom level. While zooming out, the individual markers are combined to form a single group and displayed as a single marker.
Solution
You can group the marker of imagery layer based on its zoom level by subscribing the ZoomLevelChanging event of the imagery layer and dynamically changing the markers based on the current zoom level.
Step 1: Initialize the CustomMarker class as demonstrated in the following code sample.
/// <summary> /// The custom marker /// </summary> public class CustomMarker : MapMarker { /// <summary> /// Gets or sets the image source /// </summary> public ImageSource ImageName { get; set; } }
Step 2: Initialize the SfMaps control and add the ImageryLayer into the layer collection of the control. Then, subscribe the ZoomLevelChanging event as demonstrated in the following code sample.
XAML
<maps:SfMaps > <maps:SfMaps.Layers> <maps:ImageryLayer x:Name="imageryLayer" ZoomLevelChanging="ImageryLayer_ZoomLevelChanging"> </maps:ImageryLayer> </maps:SfMaps.Layers> </maps:SfMaps>
C#
/// <summary> /// This method is called whenever the zoom level changed /// </summary> /// <param name="sender">The sender</param> /// <param name="e">The zoom level changing event args</param> private void ImageryLayer_ZoomLevelChanging(object sender,ZoomLevelChangingEventArgs e) { }
Step 3: Add CustomMarker into the Markers collection of ImageryLayer as demonstrated in the following code sample.
C#
public MainPage() { InitializeComponent(); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "20.766387", Longitude = "78.750000", ImageName = ImageSource.FromResource("Grouping_maps.Icons.pin.png") }); }
Step 4: Set template to markers added into the collection using the MarkerTemplate property of ImageryLayer as demonstrated in the following code sample.
XAML
<maps:ImageryLayer.MarkerTemplate> <OnPlatform x:TypeArguments="DataTemplate"> <On Platform="Android, iOS"> <DataTemplate> <Grid> <Image Source="{Binding ImageName}" HorizontalOptions="Start" VerticalOptions="Center" HeightRequest="30" WidthRequest="30"/> </Grid> </DataTemplate> </On> <On Platform="UWP"> <DataTemplate> <Grid Padding="-14,-14, 0, 0"> <Image Source="{Binding ImageName}" HorizontalOptions="Start" VerticalOptions="Center" HeightRequest="30" WidthRequest="30"/> </Grid> </DataTemplate> </On> </OnPlatform> </maps:ImageryLayer.MarkerTemplate>
Step 5: In the ZoomLevelChanging event, based on the CurrentLevel, add the markers and remove from marker collection to achieve marker grouping based on the zoom level.
In the following code sample, single marker is maintained for zoom level 3 and below. For zoom level 4 and above, multiple markers are maintained.
C#
/// <summary> /// This method is called whenever the zoom level changes and the markers can be grouped based on your requirement with this event /// </summary> /// <param name="sender">The sender</param> /// <param name="e">The zoom level changing event args</param> private void ImageryLayer_ZoomLevelChanging(object sender, ZoomLevelChangingEventArgs e) { // Marker is added based on the zoom level if (e.CurrentLevel <= 3) { if(imageryLayer.Markers.Count > 1) { imageryLayer.Markers.Clear(); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "20.766387", Longitude = "78.750000", ImageName = ImageSource.FromResource("Grouping_maps.Icons.pin.png") }); } } if (e.CurrentLevel >= 4) { if (imageryLayer.Markers.Count == 1) { imageryLayer.Markers.Clear(); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "12.331952", Longitude = "78.002930", ImageName = ImageSource.FromResource("Grouping_maps.Icons.one.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "17.678045", Longitude = "78.793945", ImageName = ImageSource.FromResource("Grouping_maps.Icons.two.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "18.346705", Longitude = "73.608398", ImageName = ImageSource.FromResource("Grouping_maps.Icons.three.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "21.486297", Longitude = "84.418945", ImageName = ImageSource.FromResource("Grouping_maps.Icons.four.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "22.139076", Longitude = "72.905273", ImageName = ImageSource.FromResource("Grouping_maps.Icons.five.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "26.463197", Longitude = "81.166992", ImageName = ImageSource.FromResource("Grouping_maps.Icons.six.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "26.463197", Longitude = "74.487305", ImageName = ImageSource.FromResource("Grouping_maps.Icons.seven.png") }); imageryLayer.Markers.Add(new CustomMarker() { Latitude = "28.952879", Longitude = "77.915039", ImageName = ImageSource.FromResource("Grouping_maps.Icons.eight.png") }); } } }
The following screenshot illustrates the output when zoom level is 1.
The following screenshot illustrates the output when zoom level is 4.
You can download the demo sample from this link.