Ok, so it looks like you have three different buttons (tabs), each for a different metric in your data. When one is pressed, you want the related metric to be used to change the color on the map. There are many different ways to do.
- If all the metrics are within the properties of each shape, then you would simply need to update the
fillColor
setting of the polygon layer with a new data driven expression based on the metric you want to use. - If the metrics are separate from the shapes (maybe you have a lookup table of IDs to values), you can either join the shapes with these values ahead of time or create a data driven expression that lists all ID's and their related metric value, within a larger expression that uses that value to generate the style. This method is much more intensive on the system than the first one but would work fine with smaller datasets (couple hundred shapes).
I recommend doing #1, and if need be, join the metrics to the shapes ahead of time (loop through shapes and add related metrics to the properties of the shape).
There are many different ways to create data driven styles, as documented here: https://learn.microsoft.com/en-us/azure/azure-maps/data-driven-style-expressions-web-sdk
The first thing you will need to do is determine the min/max range of your data metrics, what color you want to make the metrics, and if you want to use a gradient scale or a stepped scale (a range of values would have the same color).
Below I'll put together an example where I made the following assumptions (mainly to show the different styling methods):
Properties for each shape:
-
cost
- The cost per shipment. Min: 0, Max: 100. Use a gradient scale since the values can be floats. -
orderSize
- Shipments per order. Min: 0, Max: 10 (Anything larger than 10 will be the same color as 10, and thus that color would represent 10). Use a stepped color scale since the values would be integers. -
suboptimal
- The sub-optimal shipments percentage value. Min: 0, Max: 1. Use a gradient scale since the values can be floats.
I'll bring in state boundary data and do a join on the data with custom metrics at run time before rendering it. This can be skipped if your shape data already has the metrics in the properties of the shapes.
Here is an example of what a single shape data might look like.
{
type: 'Feature',
properties: {
cost: 8.53,
orderSize: 3,
suboptimal: 2
},
geometry: ...
}
Here is the full 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/2/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script>
var map, datasource, polygonLayer;
//Link to shape boundaries. Note I'm using a CORs proxy for this example. For security, you should host this data in your site on the same domain.
var stateBoundaries = 'https://corsproxy.io/?https://samples.azuremaps.com/data/geojson/US_States_500k.json';
var metrics = {
'Alabama': {cost:42.93,orderSize:1,suboptimal:0.57},
'Alaska': {cost:41.53,orderSize:5,suboptimal:0.17},
'Arizona': {cost:28.24,orderSize:9,suboptimal:0.61},
'Arkansas': {cost:56.3,orderSize:1,suboptimal:0.11},
'California': {cost:19.22,orderSize:4,suboptimal:0.34},
'Colorado': {cost:40.22,orderSize:9,suboptimal:0.33},
'Connecticut': {cost:98.21,orderSize:6,suboptimal:0.19},
'Delaware': {cost:34.1,orderSize:0,suboptimal:0.47},
'District of Columbia': {cost:9.21,orderSize:1,suboptimal:0.85},
'Florida': {cost:15.5,orderSize:5,suboptimal:0.03},
'Georgia': {cost:84.94,orderSize:5,suboptimal:0.66},
'Hawaii': {cost:77.04,orderSize:3,suboptimal:0.15},
'Idaho': {cost:64.58,orderSize:1,suboptimal:0.16},
'Illinois': {cost:1.95,orderSize:7,suboptimal:0.17},
'Indiana': {cost:33.37,orderSize:4,suboptimal:0.34},
'Iowa': {cost:2.91,orderSize:7,suboptimal:0.28},
'Kansas': {cost:65.32,orderSize:7,suboptimal:0.76},
'Kentucky': {cost:83.38,orderSize:6,suboptimal:0.88},
'Louisiana': {cost:15.16,orderSize:6,suboptimal:0.72},
'Maine': {cost:97.68,orderSize:8,suboptimal:0.74},
'Maryland': {cost:2.77,orderSize:3,suboptimal:0.94},
'Massachusetts': {cost:77.32,orderSize:9,suboptimal:0.58},
'Michigan': {cost:56.29,orderSize:6,suboptimal:0.93},
'Minnesota': {cost:0.74,orderSize:0,suboptimal:0.95},
'Mississippi': {cost:78.9,orderSize:8,suboptimal:0.74},
'Missouri': {cost:98.15,orderSize:0,suboptimal:0.37},
'Montana': {cost:47.73,orderSize:6,suboptimal:0.87},
'Nebraska': {cost:77.19,orderSize:10,suboptimal:0.12},
'Nevada': {cost:49.14,orderSize:9,suboptimal:0.79},
'New Hampshire': {cost:58.94,orderSize:10,suboptimal:0.48},
'New Jersey': {cost:92.78,orderSize:10,suboptimal:0.92},
'New Mexico': {cost:5.06,orderSize:0,suboptimal:0.01},
'New York': {cost:64.23,orderSize:1,suboptimal:0.29},
'North Carolina': {cost:24.49,orderSize:3,suboptimal:0.79},
'North Dakota': {cost:98.86,orderSize:1,suboptimal:0.16},
'Ohio': {cost:49.74,orderSize:10,suboptimal:0.38},
'Oklahoma': {cost:72.52,orderSize:9,suboptimal:0.5},
'Oregon': {cost:75.56,orderSize:1,suboptimal:0.83},
'Pennsylvania': {cost:26.49,orderSize:8,suboptimal:0.94},
'Puerto Rico': {cost:16.86,orderSize:8,suboptimal:0.31},
'Rhode Island': {cost:57.16,orderSize:1,suboptimal:0.59},
'South Carolina': {cost:98.85,orderSize:8,suboptimal:0.35},
'South Dakota': {cost:71.87,orderSize:2,suboptimal:0.7},
'Tennessee': {cost:2.96,orderSize:0,suboptimal:0.59},
'Texas': {cost:57.79,orderSize:2,suboptimal:0.75},
'Utah': {cost:28.42,orderSize:9,suboptimal:0.11},
'Vermont': {cost:43.45,orderSize:5,suboptimal:1},
'Virginia': {cost:79.34,orderSize:10,suboptimal:0.39},
'Washington': {cost:55.44,orderSize:1,suboptimal:0.76},
'West Virginia': {cost:71.95,orderSize:2,suboptimal:0.07},
'Wisconsin': {cost:52.35,orderSize:6,suboptimal:0.69},
'Wyoming': {cost:59.87,orderSize:10,suboptimal:0.16}
};
var styles = {
//A linear interpolation on cost from 0 (green) to 100+ (red), with the mid-point (50) being yellow.
cost: [
'interpolate',
['linear'],
['get', 'cost'], //Grab the `cost` metric from the shapes properties.
0, 'green',
50, 'yellow',
100, 'red'
],
//A stepped color scale of ranges.
orderSize: [
'step',
['get', 'orderSize'], //Grab the `orderSize` metric from the shapes properties.
'blue', //<1
1, '#a6cee3', //1 - 2
2, '#1f78b4', //2 - 3
3, '#b2df8a', //3 - 4
4, '#33a02c', //4 - 5
5, '#fb9a99', //5 - 6
6, '#e31a1c', //6 - 7
7, '#fdbf6f', //7 - 8
8, '#ff7f00', //8 - 9
9, '#cab2d6', //9 - 10
10, '#6a3d9a' //10>
],
//A linear interpolation on the sub-optimal shipment percentage from 0 (green) to 1+ (red), with the mid-point (0.5) being yellow.
suboptimal: [
'interpolate',
['linear'],
['get', 'suboptimal'], //Grab the `suboptimal` metric from the shapes properties.
0, 'green',
0.5, 'yellow',
1, 'red'
]
};
function GetMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-94.6, 39.1],
zoom: 3,
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 () {
//Create a data source and add it to the map.
datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Load the US state boundary data, then join it with the metrics.
datasource.importDataFromUrl(stateBoundaries).then(joinMetrics);
//Add a layer for rendering filled polygon area.
polygonLayer = new atlas.layer.PolygonLayer(datasource);
map.layers.add(polygonLayer);
//Set default metric.
setMetric('cost');
});
}
function setMetric(metric){
//Update the fill color style option based on the metric.
polygonLayer.setOptions({ fillColor: styles[metric] });
}
function joinMetrics() {
datasource.getShapes().forEach(state => {
//Cross reference the state shapes with the metrics using the states NAME property.
//Join the metrics with the state shapes properties.
var props = state.getProperties();
Object.assign(props, metrics[props.NAME]);
state.setProperties(props);
});
}
</script>
<style>
body, html, #myMap {
margin: 0;
padding:0;
width:100%;
height:100%;
}
.buttonPanel {
position: absolute;
top: 10px;
left:10px;
}
</style>
</head>
<body onload="GetMap()">
<div id="myMap"></div>
<div class="buttonPanel">
<button onclick="setMetric('cost')">Cost per Shipment</button>
<button onclick="setMetric('orderSize')">Shipments per order</button>
<button onclick="setMetric('suboptimal')">Sub-optimal Shipments</button>
</div>
</body>
</html>