Azure Maps LineLayerOptions strokeDashArray Data-Driven Expression

Ken Bowman 231 Reputation points
2024-09-26T17:28:00.26+00:00

Hi,

I'm trying to set a data-driven expression for a LineLayer's strokeDashArray (which should accept number[] | undefined). Is this supported and if so, how can I set it?

Thanks,

Ken

Here is my current attempt (I am successfully using something similar with a "match" for the SymbolLayer's font):

private createLineLayerOptions(lineStyle: ILineStyle): atlas.LineLayerOptions {
        return {
            strokeColor: [
                'case',
                ['has', 'lineStyle'],
                ['get', 'color', ['get', 'lineStyle']],
                lineStyle.color
            ],
            // This works for the entire layer:
            //strokeDashArray: lineStyle.dashArray.length ? lineStyle.dashArray : undefined
            strokeDashArray: [
                'case',
                ['has', 'lineStyle'],
                ['match', ['get', 'dashArray', ['get', 'lineStyle']],
                    [4, 4], ['literal', [4, 4]],
                    [2, 4], ['literal', [2, 4]],
                    [4, 4, 2, 4], ['literal', [4, 4, 2, 4]],
                    undefined
                ],
                lineStyle.dashArray.length ? ['literal', lineStyle.dashArray] : undefined
            ],
            strokeOpacity: [
                'case',
                ['has', 'lineStyle'],
                ['get', 'opacity', ['get', 'lineStyle']],
                lineStyle.opacity
            ],
            strokeWidth: [
                'case',
                ['has', 'lineStyle'],
                ['get', 'width', ['get', 'lineStyle']],
                lineStyle.width
            ]
        }
    }
Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
734 questions
0 comments No comments
{count} votes

Accepted answer
  1. rbrundritt 18,671 Reputation points Microsoft Employee
    2024-09-26T18:17:46.27+00:00

    strokeDashArray does not support data driven styling. There is a feedback item being tracked here.

    If you need to have different styles of dash arrays, one way around this limitation is to use multiple layers with filters. For example, using your code as a starting point, if we limit the dash arrays to a specific set of allowed values, we can do something like the following:

    //A list of all allowed/supported dash arrays.
    private supportedDashArray: number[][] = [
    	[4,4],
    	[2,4],
    	[4, 4, 2, 4]	
    ];
    
    
    private createLineLayers(source: atlas.surce.DataSource, lineStyle: ILineStyle){
    	const layers = [];
    	
    	//Loop through the list of supported dash arrays and create a layer for each.
    	supportedDashArray.forEach(dashArray => {
    		layers.push(new atlas.layer.LineLayer(source, null, createLineLayerOptions(lineStyle, dashArray)));
    	});
    	
    	//Add a default layer to handle undefined or unsupported dash arrays.
    	layers.push(new atlas.layer.LineLayer(source, null, createLineLayerOptions(lineStyle)));
    
    	return layers;
    }
    
    private createLineLayerOptions(lineStyle: ILineStyle, dashArray: number[] | undefined): atlas.LineLayerOptions {
    
    	return {
    		strokeColor: [
    			'case',
    			['has', 'lineStyle'],
    			['get', 'color', ['get', 'lineStyle']],
    			lineStyle.color
    		],
    		// This works for the entire layer:
    		//strokeDashArray: lineStyle.dashArray.length ? lineStyle.dashArray : undefined
    		strokeDashArray: dashArray,
    		strokeOpacity: [
    			'case',
    			['has', 'lineStyle'],
    			['get', 'opacity', ['get', 'lineStyle']],
    			lineStyle.opacity
    		],
    		strokeWidth: [
    			'case',
    			['has', 'lineStyle'],
    			['get', 'width', ['get', 'lineStyle']],
    			lineStyle.width
    		],
    		filter: createDashArrayFilter(dashArray)
    	}
    }
    
    
    private createDashArrayFilter(dashArray: number[] | undefined) {
    
    	if(dashArray) {
    		//Note that a match/comparison can't be done on an array directly in a style expression since an array is seen as an expression. 
    		//Converting the array to a string makes for easier comparison.
    		
    		const dashArrayString = `[${dashArray.toString()}]`;	//Will create a string like '[1,2,3]'	
    		
    		return [
    			//AND comparison of conditions.
    			'all', 
    			
    			//Ensure the shape has a lineStyle.dashArray property.
    			['has', 'linestyle'], 
    			['has', 'dashArray', ['get', 'lineStyle']],
    			
    			//Compare the string versions of the dashArray values.
    			[
    				'==',
    				
    				//Convert the shapes dashArray porperty to string.
    				['to-string', ['get', 'dashArray', ['get', 'lineStyle']]],	//Will create a string like '[1,2,3]'	
    				
    				dashArrayString			
    			]
    		];	
    	} else {
    		//Convert the list of supported dash arrays to a list of strings we can compare against.
    		const stringDashArrays = [];
    		
    		//Loop through the list of supported dash arrays and create a layer for each.
    		supportedDashArray.forEach(dash => {
    			stringDashArrays.push(`[${dash.toString()}]`);
    		});
    	
    		//Check that it doesn't have a dash array property.
    		return [	
    			//Do the opposite of the following check.
    			'!',
    			
    			//Check to see if the shape has a valid dash array property and allowed value.
    			[
    				//AND comparison of conditions.
    				'all', 
    				
    				//Ensure the shape has a lineStyle.dashArray property.
    				['has', 'linestyle'], 
    				['has', 'dashArray', ['get', 'lineStyle']],
    				
    				//Optionally, also handle any dash arrays that aren't supported. 
    				//Check to see if the dash array pattern is an allowed/supported one.
    				['in', ['to-string', ['get', 'dashArray', ['get', 'lineStyle']]], ['literal', stringDashArrays]]
    			]
    		];
    	}
    }
    

    Note that Azure Maps wraps MapLibre (fork of Mapbox) and adds a layer to the API that makes it easier to develop applications, and create /maintain common scenarios. However, when it comes to style expression support, Azure Maps will only support as much as MapLibre does. Also note that the Azure Maps team is involved in the MapLibre developer community and does help add improvements at that level.


0 additional answers

Sort by: Most helpful

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.