Azure-Samples/AzureMapsCodeSamples

Changing map style changes layering

Jxlle opened this issue · 10 comments

Jxlle commented

When I start my map, the layering is how I want it: Simplified: World labels at the top (worldSubLabels layer), polygon icons under that (invalidStockSymbols layer) and polygons at the bottom (polygons layer).
image

When I change to any other style if the map has already loaded (with the controls in the gui), the map layer order seems to change: World labels at the bottom.
image

Looking at map.layers, I see no big difference:

Before:
image

After:
image

Is this a bug?

Can you provide more information on how you add your layers to the map. Do you provide a layer ID to insert your layers below another layer?

Jxlle commented

Hi @rbrundritt,

I currently insert the layers below eachother, but I believe that I had the same problem in the past when I was just adding the layers without inserting them before another layer. This is how I currently handle layering:

    // Top Layer: Visualisation of the main world location label
    mainWorldLocationDataSource= new atlas.source.DataSource('worldMainSource');
    mainWorldLocationDataSource.add(new atlas.Shape(new atlas.data.Point(...)));
    map.sources.add(mainWorldLocationDataSource);
    map.layers.add(new atlas.layer.SymbolLayer(mainWorldLocationDataSource, 'worldMainLabel', {...}));

    // Layer before previous layer: Visualisation of the sub world location labels
    worldLocationDataSource = new atlas.source.DataSource('worldSubSource');
    worldLocationDataSource.add(JSON.parse(JSON.stringify(...)));
    map.sources.add(worldLocationDataSource);
    map.layers.add(new atlas.layer.SymbolLayer(worldLocationDataSource, 'worldSubLabels', {...}), 'worldMainLabel');
    
    // Layer before previous layer
    ....
    
    // etc.

I'm able to reproduce this issue. Looks like a new bug, most likely related to the new base map styling they added recently. I'll send this over to the Azure Maps team so they can investigate.

bh3605 commented

@rbrundritt Does azure-maps-control not have a public github repository? I tried using the bouncing marker animation sample using the 'azure-maps-control' npm package and the interface no longer matches what the sample says to do. It's been a real PITA trying to find the code base for this. It'd be bonkers for this not to live in a public github repo when so many of Microsoft's other javascript npm packages are.

This is the first time anyone asked for it to be open source. There were discussions with the MapLibre community about making the Azure Maps source code open source (Azure Maps Web SDK is a wrapper around that control and provides an enhanced API interface and features). That community wasn't that interested in it at the time, and only wanted certain features which the team has shared back with them. Not sure what the future plans are as I'm not on the Azure Maps team. As for other open-source Microsoft JavaScript libraries, most are autogenerated REST clients, while most UI based controls are not open source.

As for the issue with the animation module, this is the first time I've heard of that one, and that module has been around for years and is used a lot. I'll see if I can reproduce the issue you are seeing.

Note, if all you want is a bouncing marker, don't bother with the animation library, you would be loading a lot of extra code for nothing. Simply use a CSS animation with the HTML marker. For example:

<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>

    <meta charset="utf-8" />    
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

    <!-- 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>

    <script>
        var map;

        function GetMap() {
            //Initialize a map instance.
            map = new atlas.Map('myMap', {
                view: 'Auto',

                //Add authentication details for connecting to Azure Maps.
                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: '<Your Azure Maps Key>'
                }
            });
			
            //Wait until the map resources are ready.
            map.events.add('ready', function () {				
				
		//Get marker HTML from templates
		var svg = atlas.getImageTemplate('marker');
		
		//Replace template placeholders with values.
		svg = svg.replace('{color}', 'DodgerBlue').replace('{text}', '');
		
		//Load SVG icon template into marker icon div.				
		var markerIcon = document.createElement('div');
		markerIcon.innerHTML = svg;
		
		//Add bouncing CSS class animation to the wrapped SVG icon.
		markerIcon.firstChild.classList.add('bouncing');
							
                //Create a draggable HTML marker.
                var marker = new atlas.HtmlMarker({
                    htmlContent: markerIcon,
                    position: [0, 0]
                });

                //Add the marker to the map.
                map.markers.add(marker);
            });
		}
    </script>
	<style> 
		html, body { 
			margin:0;
			padding:0;
			width: 100%;
			height: 100%;
		} 
		
		#myMap {
			position: relative;			
			width: 100%;
			height: 100%;
		}
		
		.bouncing { 
			animation: bounce 0.5s; 
			animation-direction: alternate; 
			animation-timing-function: cubic-bezier(.5, 0.05, 1, .5); 
			animation-iteration-count: infinite; 
		} 
		
		@keyframes bounce { 
			from { 
				transform: translate(0, -50px); 
			} 
			to { 
				transform: translate(0, 0); 
			} 
		} 
	</style> 
</head> 
<body onload='GetMap()'>
    <div id="myMap"></div>
</body> 
</html> 
bh3605 commented

@rbrundritt Thanks for the bouncing marker. Looks more effective than the sample. So we had to shift from Google Maps to Azure Maps for privacy reasons. Maybe I'll just create an issue in this repository if I come across any bugs or feature requests. I have one to ask how to add a button that will re-center the map to a known marker.

I'm surprised I'm the first to ask about making the azure map related js libs open source. This is a great alternative to Google Maps. I like how you have some separation between the map and the map api (azure-maps-control and azure-maps-rest). I think it's cool you have an actual class that holds your api token that can be used for both the map and the api. The MapControlCredential class. It feels intuitive to have it be open source when you have all the code in front of you anyway.

Glad to hear you like the Azure Maps Web SDK. I designed the original API interface for it and spent a lot of time trying to make things line up seamlessly to make the most sense.

Since you are new to Azure Maps, here are a few key resources:

As for your question on using a button to recenter on a marker, there are several ways to do this.

If you simply want to just center the map and don't really need to interact with the mark (e.g. display a popup or start/stop some animation), you can simply have the button pass the markers lat/lon values into a function to center the map. Here is a simple example:

<input type="button" value="Center" onclick="map.setCamera({ center: [45, -110], zoom: 14 })" />

If you need a reference to the marker for some reasons, the tricky part is having a way to cross reference the button to the marker/shape. You could add a click event in code that has direct access to the marker reference, but that isn't that efficient if you have a lot of markers as you would end up with each button having its own click event. Instead, store a unique string value for each marker in each button (assuming you have multiple buttons). Using the rel property of the button to store a string value is pretty common. From there you can grab this value when the button is clicked and then do a look up for the marker/shape in question. For example:

var marker = new atlas.HtmlMarker(...);

//Store properties in a marker,
marker.properties = { id: 1234 };

//Example of a button that has the marker ID stored in the rel property.
<input type="button" value="Center" onclick="buttonClicked(this)" rel="1234" />

//Function called by button that gets the stored ID value, looks up the marker in question, and centers the map on it.
function buttonClicked(btnElm) {
    var id = btnElm.rel;
    var marker = map.markers.getMarkers().find(m => m.properties.id == id);
    map.setCamera({ center: marker.getOptions().position, zoom: 14 });
}

The Azure Maps Web SDK team has confirmed that this issue has been fixed in latest version of the SDK (released Jan 12th). See the bug fixes section of the 3.1.0 release here: https://learn.microsoft.com/en-us/azure/azure-maps/release-notes-map-control#v3-latest