azuremapsazure-maps

Trying to Add Label And Text to Markers inside Cluster Layer


I've performed clustering using the sample code provided by Azure Maps. However, I've utilized my own collection of latitude and longitude coordinates.

My issue arises when attempting to add labels and text to the shape points. Despite trying to add them, it doesn't seem to be functioning as expected. I've also experimented with adding HTML markers to the data source, but unfortunately, that hasn't yielded the desired results either. Below is my sample code.

Additionally, I'd like to inquire if there are alternative methods available to add markers into clusters. Any insights on this would be greatly appreciated.

Point Clusters in Bubble Layer - Azure Maps Web SDK Samples
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description"
    content="This sample shows how to enable point based clustering on a data source and render them differently from individual points on the map." />
<meta name="keywords"
    content="Microsoft maps, map, gis, API, SDK, markers, pins, pushpins, symbols, layer, bubbles, clustering, superclusterer, earthquakes, USGS" />
<meta name="author" content="Microsoft Azure Maps" />
<meta name="version" content="1.0" />
<meta name="screenshot" content="screenshot.jpg" />
<script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>

<!-- Load the code for the Spider Cluster Manager. -->
<script src="Static/lib/azure-maps/azure-maps-spider-clusters.min.js"></script>

<script>
    var map, datasource, datasource2, routeURL, popup, spiderManager;

    //GeoJSON feed of all earthquakes from the past 30 days. Sourced from the USGS.
    var earthquakeFeed = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson';

    //Find more earthquake data feeds here: https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php

    function GetMap() {
        //Initialize a map instance.
        map = new atlas.Map('myMap', {
            center: [-97, 39],
            zoom: 3,
            // style: 'night',
            view: 'Auto',

            //Add authentication details for connecting to Azure Maps.
            authOptions: {
                //Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
                authType: 'subscriptionKey',
                subscriptionKey: ''
            }
        });
        var pipeline = atlas.service.MapsURL.newPipeline(new atlas.service.MapControlCredential(map));
        //Construct the RouteURL object
        routeURL = new atlas.service.RouteURL(pipeline);
        //Wait until the map resources are ready.
        map.events.add('ready', function () {
            var pipeline = atlas.service.MapsURL.newPipeline(new atlas.service.MapControlCredential(map));
            //Construct the RouteURL object
            routeURL = new atlas.service.RouteURL(pipeline);
            // console.log(a);
            timePass()
        });
    }
    function timePass() {

        datasource = new atlas.source.DataSource(null, {
            //Tell the data source to cluster point data.
            cluster: true,

            //The radius in pixels to cluster points together.
            clusterRadius: 45,

            //The maximium zoom level in which clustering occurs.
            //If you zoom in more than this, all points are rendered as symbols.
            clusterMaxZoom: 15
        });
        map.sources.add(datasource);

        //Create a bubble layer for rendering clustered data points.
        var clusterBubbleLayer = new atlas.layer.BubbleLayer(datasource, null, {
            createIndicators: true, // to enable bubble layer a11y feature
            //Scale the size of the clustered bubble based on the number of points in the cluster.
            radius: [
                'step',
                ['get', 'point_count'],
                20,         //Default of 20 pixel radius.
                100, 30,    //If point_count >= 100, radius is 30 pixels.
                750, 40     //If point_count >= 750, radius is 40 pixels.
            ],

            //Change the color of the cluster based on the value on the point_cluster property of the cluster.
            color: [
                'step',
                ['get', 'point_count'],
                'rgba(0,255,0,0.8)',            //Default to green. 
                100, 'rgba(255,255,0,0.8)',     //If the point_count >= 100, color is yellow.
                750, 'rgba(255,0,0,0.8)'        //If the point_count >= 100, color is red.
            ],
            strokeWidth: 0,
            filter: ['has', 'point_count'] //Only rendered data points which have a point_count property, which clusters do.
        });



        //Add a click event to the layer so we can zoom in when a user clicks a cluster.
        map.events.add('click', clusterBubbleLayer, clusterClicked);

        // Add mouse events to change the mouse cursor when hovering over a cluster.
        map.events.add('mouseenter', clusterBubbleLayer, function () {
            map.getCanvasContainer().style.cursor = 'pointer';
        });

        map.events.add('mouseleave', clusterBubbleLayer, function () {
            map.getCanvasContainer().style.cursor = 'grab';
        });
        var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
            filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
        })
        //Add the clusterBubbleLayer and two additional layers to the map.
        map.layers.add([
            clusterBubbleLayer,

            //Create a symbol layer to render the count of locations in a cluster.
            new atlas.layer.SymbolLayer(datasource, null, {
                iconOptions: {
                    image: 'none' //Hide the icon image.
                },
                textOptions: {
                    textField: ['get', 'point_count_abbreviated'],
                    offset: [0, 0.4]
                }
            }),
            shapeLayer

            //Create a layer to render the individual locations.

        ]);
        var coordinates = [
            [40.7128, -74.0060],
            [34.0522, -118.2437],
            [41.8781, -87.6298],
            [29.7604, -95.3698],
            [33.4484, -112.0740],
            [39.9526, -75.1652],
            [37.7749, -122.4194],
            [32.7767, -96.7970],
            [30.2672, -97.7431],
            [35.2271, -80.8431],
            [49.6062, -122.3321],
            [25.7617, -80.1918],
            [42.3601, -71.0589],
            [38.9072, -77.0369],
            [36.7783, -119.4179],
            [33.7490, -84.3880],
            [34.0522, -118.2437],
            [40.7128, -74.0060],
            [37.7749, -122.4194],
            [41.8781, -87.6298],
            [32.7157, -117.1611],
            [39.2904, -76.6122],
            [29.7604, -95.3698],
            [33.4484, -112.0740],
            [35.2271, -80.8431],
            [30.2672, -97.7431],
            [34.0522, -118.2437],
            [42.3601, -71.0589],
            [38.9072, -77.0369],
            [36.7783, -119.4179],
            [33.7490, -84.3880],
            [40.7128, -74.0060],
            [37.7749, -122.4194],
            [41.8781, -87.6298],
            [32.7157, -117.1611],
            [39.2904, -76.6122],
            [29.7604, -95.3698],
            [33.4484, -112.0740],
            [35.2271, -80.8431],
            [30.2672, -97.7431],
            [34.0522, -118.2437],
            [42.3601, -71.0589],
            [38.9072, -77.0369],
            [36.7783, -119.4179],
            [33.7490, -84.3880],
            [40.7128, -74.0060],
            [37.7749, -122.4194],
            [41.8781, -87.6298],
            [32.7157, -117.1611],
            [39.2904, -76.6122],
            [29.7604, -95.3698],
            [33.4484, -112.0740],
            [35.2271, -80.8431],
            [30.2672, -97.7431],
            [34.0522, -118.2437],
            [42.3601, -71.0589],
            [38.9072, -77.0369],
            [36.7783, -119.4179],
            [33.7490, -84.3880],
            [40.7128, -74.0060],
        ]
        var marker;
        var pins = [];
        coordinates.forEach(function (data, index) {
            // marker = new atlas.HtmlMarker({
            //          color: 'DodgerBlue',
            //          text:index+"",
            //          position: [data[1],data[0],]
            //      });
            marker = new atlas.Shape(new atlas.data.Point([data[1], data[0]]), {
                color: 'DodgerBlue',
                text: "Nilesh",
                label: "Nilesh"

            });
            // marker = new atlas.data.Point([data[1], data[0]]), {
            //     color: 'DodgerBlue',
            //     text:"Nilesh",
            //     label:"Nilesh"
            // };
            // marker.addProperty('name', "Nilesh");
            datasource.add(marker);
            pins.push(marker);
        })
    }
    function clusterClicked(e) {
        if (e && e.shapes && e.shapes.length > 0 && e.shapes[0].properties.cluster) {
            //Get the clustered point from the event.
            var cluster = e.shapes[0];

            //Get the cluster expansion zoom level. This is the zoom level at which the cluster starts to break apart.
            datasource.getClusterExpansionZoom(cluster.properties.cluster_id).then(function (zoom) {

                //Update the map camera to be centered over the cluster. 
                map.setCamera({
                    center: cluster.geometry.coordinates,
                    zoom: zoom,
                    type: 'ease',
                    duration: 200
                });
            });
        }
    }
</script>
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
    <legend>Point Clusters in Bubble Layer</legend>
    This sample shows how to enable point based clustering on a data source and render them differently from
    individual points on the map. Clustered points have four properties;

    <ul>
        <button style="height: 100px;width: 100px;background-color: aqua;" onclick="timePass()"></button>
        <li>cluster - A boolean value indicating that it is a cluster.</li>
        <li>cluster_id - A unique id for the cluster which can be used with the DataSource getClusterExpansionZoom,
            getClusterChildren, and getClusterLeaves functions.</li>
        <li>point_count - The number of points the cluster contains.</li>
        <li>point_count_abbreviated - A string that abbreviates the point_count value if it is long. (i.e. 4,000
            becomes 4K)</li>
    </ul>
</fieldset>

I want to Add Label And Text TO the Markers Into Cluster Layer


Solution

  • I'm assuming you have a function called clusterClicked as that was the first error I ran into when I tried to run the code you provided.

    Looking at your code you only have one layer that is adding labels;

    //Create a symbol layer to render the count of locations in a cluster.
    new atlas.layer.SymbolLayer(datasource, null, {
        iconOptions: {
            image: 'none' //Hide the icon image.
        },
        textOptions: {
            textField: ['get', 'point_count_abbreviated'],
            offset: [0, 0.4]
        }
    }),
    

    This could would only display the point count information as a label, and that would only appear for the clusters. It would likely be a good idea to add a filter for clusters to this layer as well. Add the following: filter: ['has', 'point_count']

    The code for your shape layer looks like the following:

    var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
         filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
    })
    

    This code doesn't add any text label for the individual shapes, thus the "Test" labels are not appearing. You can modify the code as follows to show the label:

    var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
        textOptions: {
            textField: ['get', 'label'], //Alternatively replace with 'label' property name.
            anchor: "top", //Show the label below the pin.
            color: ['get', 'color'], //Set the color of the text. Alternatively pass in a color value here if the color will always be one color.
        },
        filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
    })
    

    Note that some labels may be hidden if they overlap with anything. You can make them always appear by adding the following options to the symbol layer:

    allowOverlap: true,
    ignorePlacement: true
    

    Now, the labels still will not show up if you make these changes. The last issue is that you are passing the properties into the id filed of the Shape constructor. You can set the id to null and the map will automatically assign a unique id. Modify your code as follows:

    marker = new atlas.Shape(new atlas.data.Point([data[1], data[0]]), null, {
        color: 'DodgerBlue',
        text: "Test",
        label: "Test"
    
    });
    

    Using a symbol layer is the best route to go as it easily supports data driven styling and can handle tens of thousands of shapes easily, while Html markers typically run into performance issues once you get into the hundreds.