How to Plot Multiple SVG Icons with Dynamic Numbers in Azure Maps?

Nilesh Khonde 80 Reputation points
2025-01-28T10:51:33.1133333+00:00

In my recent project, I needed to plot multiple SVG icons, each displaying different numbers. Since I'm new to this, I wasn't sure how to approach it and ended up creating a new SVG and adding it to the imageSprite for each number.

plotRouteMarkersOnMap(position:any,mapData:any,address:any,index:any){

        try {

            //form a marker unique key for imagesprite

            const markerKey=`route_marker-${index+1}`;

            //form a svg along with number

            mapData.imageSprite.add(markerKey, `<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M20 0c8.591 0 15.556 6.268 15.556 14C35.556 26.626 20 40 20 40S4.444 26.738 4.444 14C4.444 6.268 11.41 0 20 0" fill="#FF6E6E"/></g><text x="20" y="22" font-size="15" text-anchor="middle" fill="#fff" font-family="Arial" font-weight="700">${index+1}</text><defs><clipPath id="a"><path fill="#fff" d="M0 0h40v40H0z"/></clipPath></defs></svg>`)

            const routeMarker = new atlas.Shape(new atlas.data.Point([position.lon, position.lat]), undefined, {

                title: address,

                iconImage: markerKey

            });

            this.routeDataSource.add(routeMarker);

            const Coordinates = [position.lon, position.lat]

            mapData.setCamera({

                center: Coordinates,

                zoom: 14

            });

            // Compare first and last waypoints

            if (this.waypoints.length > 1) {

                const firstWaypoint = this.waypoints[0].position;

                const lastWaypoint = this.waypoints[this.waypoints.length - 1].position;

                if (firstWaypoint.lat === lastWaypoint.lat &&firstWaypoint.lon === lastWaypoint.lon) {

                    console.warning("Your starting and ending locations are the same.","warning");

                }

            }

        } catch (error:any) {

            console.error("Error in plotWayPoints: " + error.message, 'error');          }      }    }

Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
798 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Manas Mohanty 2,035 Reputation points Microsoft External Staff
    2025-01-29T08:28:09.92+00:00

    Hi Nilesh Khonde!

    Welcome to the Microsoft Q&A and thank you for posting your questions here. To plot multiple SVG icons with dynamic numbers in Azure Maps, you can use the SymbolLayer. Here's a step-by-step guide to help you get started:

    1. Create a Data Source: First, create a data source and add it to the map.
    2. Create a Symbol Layer: Create a symbol layer and pass the data source to it.
    3. Add Data to the Data Source: Add your data points to the data source.
    4. Use SVG Icons: Use SVG icons for your symbols and customize them as needed.

     Here's a sample code snippet to illustrate this:

    function InitMap()
    {
        var map = new atlas.Map('myMap', {
            center: [-73.985708, 40.75773],
            zoom: 12,
            view: "Auto",
            //Add authentication details for connecting to Azure Maps.
            authOptions: {
                authType: 'subscriptionKey',
                subscriptionKey: '{Your-Azure-Maps-Subscription-key}'
            }
        });
        map.events.add('ready', function () {
          //Load the custom image icon into the map resources.
          map.imageSprite.add('my-custom-icon', '/images/icons/showers.png').then(function () {
            //Create a data source and add it to the map.
            var datasource = new atlas.source.DataSource();
            map.sources.add(datasource);
            //Create a point feature and add it to the data source.
            datasource.add(new atlas.data.Feature(new atlas.data.Point([-73.985708, 40.75773]), {
              temperature: 64
            }));
            //Add a layer for rendering point data as symbols.
            map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
              iconOptions: {
                //Pass in the id of the custom icon that was loaded into the map resources.
                image: 'my-custom-icon',
                //Optionally scale the size of the icon.
                size: 0.5
              },
              textOptions: {
                //Convert the temperature property of each feature into a string and concatenate "°F".
                textField: ['concat', ['to-string', ['get', 'temperature']], '°F'],
                //Offset the text so that it appears on top of the icon.
                offset: [0, -2]
              }
            }));
          });
        });
    }
    

    You can also upload Geo Json file containing the co-ordinates and respective temperature, later to be replaced with icons.

    Kindly refer these docs -

    Add a Symbol layer to a map | Microsoft Learn

    geojson-data-source

    Thank you.

                     


  2. rbrundritt 19,846 Reputation points Microsoft Employee
    2025-02-03T19:49:03.2733333+00:00

    There are a couple of approaches you can take depending on the number of SVG icons you need to support, the complexity of your SVGs, and the number of points you want to support.

    As you likely know SVG's are XML markup that the browser can interpret within the DOM like HTML. However, the more things you have in the browser DOM, the slower the web page becomes. Azure Maps purposely moved away from relying on the DOM for rendering and instead uses WebGL. WebGL doesn't have support for SVGs, however, an SVG can be converted into a static image and used as an icon easily. Converting an SVG into a static image within the browser however has some limitations; animations, CSS classes, and custom fonts won't work within the SVG (inline CSS does work).

    If you have a small data set, and want to avoid these limitations, you can use the HTML Marker class to display your points. These use traditional DOM rendering for the points and thus SVG's would render as expected in a browser. HTML markers work fine until you start to get into the hundreds of points, then performance slows down quickly. There is no built-in layering/data source logic for the HTML markers since they are mainly there for edge case scenarios. However, if you want consistency with how data sources/layers work in Azure Maps and possibly clustering capabilities, I built an open source solution for this here: https://github.com/azure-samples/azure-maps-html-marker-layer

    That said, I highly recommend using the Symbol layer for rendering as it will support tens of thousands of points with great performance. You can add SVG's to the maps image sprite just like any other image, and the map will automatically convert the SVG to an image (just pass an SVG instead of a png into this code sample: https://samples.azuremaps.com/?sample=custom-symbol-image-icon). Note the limitations I mentioned previously would apply here. There is a limit to how much space the maps image sprite has for custom images, so if you have more than a couple dozen SVG's you may run into some issues. Note that the numbers you mentioned do not need to be in the SVG's. The Symbol layer can overlay the numbers as text on top of your SVG icons, thus allowing you to reuse the icons. A couple of tips since you have multiple icons:

    1. When adding the icons to the map image sprite, you can wait for all of them to be added using a promise like this:
    //Create an array of custom icon promises to load into the map. 
    var iconPromises = [
    	map.imageSprite.add('gas_station_icon', '/images/icons/gas_station_pin.png'),
    	map.imageSprite.add('grocery_store_icon', '/images/icons/grocery_cart_pin.png'),
    	map.imageSprite.add('restaurant_icon', '/images/icons/restaurant_pin.png'),
    	map.imageSprite.add('school_icon', '/images/icons/school_pin.png'),
    ];
    
    //Load all the custom image icons into the map resources.
    Promise.all(iconPromises).then(function () {
    
    	//Add a layer for rendering point data as symbols.
    	map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
    		iconOptions: {
    			//Use a match expression to select the image icon based on the EntityType property of the data point.
    			image: [
    				'match',
    
    				['get', 'EntityType'],
    
    				//For each entity type, specify the icon name to use.
    				'Gas Station', 'gas_station_icon',
    				'Grocery Store', 'grocery_store_icon',
    				'Restaurant', 'restaurant_icon',
    				'School', 'school_icon',
    
    				//Default fallback icon.
    				'marker-blue'
    			]
    		}
    	}));
    });
    
    1. If you look at the code you see a data driven style expression is used to determine with icon to display for each point. In this case that sample data has a property called "EntityType" which it's value is being used to select the appropriate icon.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.