Junaid Bedford
Junaid Bedford

Reputation: 1

Azure Maps SDK popup does not open after initial load

I am using Azure Maps SDK in a Blazor Server app which uses JavaScript interop. The map works well and renders perfectly.

On initial load of the map component the popup displays correctly when clicking a pin on the map. However, when the data source changes via an API call datasource.importDataFromUrl(organisationDataFeed); it correctly brings back the filtered data, but when I click on one of the pins again the popup does not display. The click event handler (for the pin) is being called, but the popup does not open.

(function () {

    var map, datasource, popup;

    // Global export
    window.azuremaps = {
        initMap: function (organisationDataFeed) {
            // Create an instance of the map control and set some options.

            map = new atlas.Map('map', {
                // center: [-97, 39],

                // center: [18.424095, -33.925000],
                center: [26.157981, -29.083937],
                zoom: 4,
                pitch: 50,
                style: 'night',
                view: 'Auto',

                // Add your Azure Maps subscription key to the map SDK. Get an Azure Maps key at https://azure.com/maps
                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: ''
                }
            });

            map.controls.add([
                new atlas.control.ZoomControl(),
                new atlas.control.CompassControl(),
                new atlas.control.PitchControl(),
                new atlas.control.StyleControl()
            ], {
                position: "top-right"
            });

            // Wait until the map resources are ready.
            map.events.add('ready', function () {

                // Create a data source and add it to the map.
                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, {
                    //Scale the size of the clustered bubble based on the number of points inthe 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';
                });

                // Create a layer to render the individual locations.
                var individualSymbolLayer = new atlas.layer.SymbolLayer(datasource, null, {
                    filter: ['!', ['has', 'point_count']], //Filter out clustered points from this layer.

                    textOptions: {
                        textField: ['get', 'name'],
                        color: "#FFFFFF",
                        offset: [0, -2.2]
                    },
                });

                map.events.add('click', individualSymbolLayer, symbolClicked);

                //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]
                        }
                    }),

                    individualSymbolLayer
                    
                ]);

                // Create a popup but leave it closed so we can update it and display it later.
                popup = new atlas.Popup({
                    pixelOffset: [0, -18],
                    closeButton: true
                });

                // Retrieve a GeoJSON data set and add it to the data source. 
                datasource.importDataFromUrl(organisationDataFeed);
            });
        },
    };

    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 + 2,
                    type: 'ease',
                    duration: 200
                });
            });
        }
    }

    function symbolClicked(e) {
        // Make sure the event occured on a point feature.
        
        var popupTemplate = '<div class="card border-success" style="visibility: visible"><div class="card-header" style="visibility: visible">{name}</div><div class="card-body text-success" style="visibility: visible"><h5 class="card-title" style="visibility: visible">{description}</h5><p class="card-text" style="visibility: visible">Contact: {contact}</p><p class="card-text">Web: {website}</p></div></div>';

        if (e.shapes && e.shapes.length > 0) {
            var content, coordinate;

            // Check to see if the first value in the shapes array is a Point Shape.
            if (e.shapes[0] instanceof atlas.Shape && e.shapes[0].getType() === 'Point') {
                var properties = e.shapes[0].getProperties();
                content = popupTemplate.replace(/{name}/g, properties.name).replace(/{description}/g, properties.description).replace(/{contact}/g, properties.contact).replace(/{website}/g, properties.website);
                coordinate = e.shapes[0].getCoordinates();
            }
            else if (e.shapes[0].type === 'Feature' && e.shapes[0].geometry.type === 'Point') {

                // Check to see if the feature is a cluster.
                if (e.shapes[0].properties.cluster) {
                    content = '<div style="padding:10px;">Cluster of ' + e.shapes[0].properties.point_count + ' symbols</div>';
                } else {
                    // Feature is likely from a VectorTileSource.
                    content = popupTemplate.replace(/{name}/g, properties.name).replace(/{description}/g, properties.description).replace(/{contact}/g, properties.contact).replace(/{website}/g, properties.website);
                }

                coordinate = e.shapes[0].geometry.coordinates;
            }
            
            if (content && coordinate) {
                // Populate the popupTemplate with data from the clicked point feature.

                console.log("JB content");
                console.log(content);

                console.log("JB coordinate");
                console.log(coordinate);

                popup.setOptions({
                    //Update the content of the popup.
                    content: content,

                    //Update the position of the popup with the symbols coordinate.
                    position: coordinate
                });

                console.log("JB: logging map variable");
                console.log(map);

                popup.open(map);
            }
        }
    }

})();

content and coordinate are populated with values and evaluate to true, the options are correctly set, but just the last line: popup.open(map); does not work if the data source changes bringing back new data into the map. It works perfectly on initial load.

Any ideas what I could do to get this working? Thanks

Upvotes: 0

Views: 941

Answers (1)

rbrundritt
rbrundritt

Reputation: 17964

A couple of things to try:

  • Double check the values of coordinate and content. The coordinates should be an array with [longitude,latitude] numbers (make sure they aren't string values of numbers). The content should either be a DOMElement (i.e. div), or a string. If it is anything else, it may not display anything.

  • Double check the "map" variable is a map the second time around. If the reference is lost for some reason, that function won't work.

  • It looks like you are create a new popup all the time. Often apps only want to display a single popup at a time. In that case it is more efficient to create a single popup and reuse it as shown in this example: https://azuremapscodesamples.azurewebsites.net/index.html?sample=Reusing%20Popup%20with%20Multiple%20Pins

Upvotes: 0

Related Questions