-
Notifications
You must be signed in to change notification settings - Fork 451
/
Accessible shape selection.html
182 lines (145 loc) · 8.72 KB
/
Accessible shape selection.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<!DOCTYPE html>
<html lang="en">
<head>
<title>Accessible shape selection - Azure Maps Web SDK Samples</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="This sample shows how to add keyboard selection support to shapes by leveraging hidden popups." />
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, popups, infobox, infowindow, events, mouse, accessibility" />
<meta name="author" content="Microsoft Azure Maps" /><meta name="version" content="1.0" />
<meta name="screenshot" content="screenshot.jpg" />
<!-- 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, datasource, lineHoverLayer
function getMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-110, 50],
zoom: 2,
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
//Use Microsoft Entra ID authentication.
authType: 'anonymous',
clientId: 'e6b6ab59-eb5d-4d25-aa57-581135b927f0', //Your Azure Maps client id for accessing your Azure Maps account.
getToken: function (resolve, reject, map) {
//URL to your authentication service that retrieves an Microsoft Entra ID Token.
var tokenServiceUrl = 'https://samples.azuremaps.com/api/GetAzureMapsToken';
fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
}
//Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
//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);
//Add a layer for rendering a different color outline of a polygon for representing a hover state.
lineHoverLayer = new atlas.layer.LineLayer(datasource, null, {
strokeColor: 'red',
strokeWidth: 5,
//Don't highlight polygons by setting the filter to a shape that has no ID value.
//All shapes in a data source are assigned a unique "_azureMapsShapeId" property value. This is the same as the ID of the shape.
filter: ['==', ['get', '_azureMapsShapeId'], '']
});
map.layers.add([
//Create a layer to render the polygon data.
new atlas.layer.PolygonLayer(datasource),
//Add a layer for rendering the styled outline of the polygon data.
new atlas.layer.LineLayer(datasource, null, {
strokeColor: 'white',
strokeWidth: 1
}),
lineHoverLayer
], 'labels');
//Download a GeoJSON feed and add the data to the data source.
datasource.importDataFromUrl('/data/geojson/US_States_Population_Density.json').then(() => {
//Loop through all shapes in the data source, create a popup that can be used to power keyboard tabbing through shapes.
var shapes = datasource.getShapes();
shapes.forEach(shape => {
//Get the properties on the shape.
var props = shape.getProperties();
//Create a popup.
var popup = new atlas.Popup({
//Add content that you want the screen reader to read out.
content: `<div style='clip:rect(1px,1px,1px,1px);height:1px;width:1px;position:absolute' aria-label="Description">Name ${props.name}. Population density ${props.density}</div>`,
//Since the popup won't be visible, it can be displayed anywhere.
position: [0, 0],
//Hide the pointer.
showPointer: false,
//Hide the close button, otherwise the user will have to press tab twice to move on to the next popup.
closeButton: false
});
//Store the ID of the shape that this popup is for so that we can use it later to retrieve the shape reference.
popup.properties = {
shapeId: shape.getId()
};
//Add the close event before the open event on the popup so that the close event fires first.
map.events.add('close', popup, popupClosed);
map.events.add('open', popup, popupOpened);
//Add the popup to the map.
map.popups.add(popup);
});
});
});
}
function popupOpened(e) {
var id = e.target.properties.shapeId;
//Get the shape that has the specified ID.
var shape = datasource.getShapeById(id);
//Show content for the shape in the display panel.
displayContent(shape);
//Highlight a polygon by setting the line filter such that the "_azureMapsShapeId" property value is the id of the shape to be highlighted.
lineHoverLayer.setOptions({ filter: ['==', ['get', '_azureMapsShapeId'], id] });
}
function popupClosed(e) {
//Don't highlight polygons by setting the filter to a shape that has no ID value.
lineHoverLayer.setOptions({ filter: ['==', ['get', '_azureMapsShapeId'], ''] });
//Hide the display panel.
document.getElementById('displayPanel').style.display = 'none';
}
function displayContent(shape) {
//Get the properties on the shape.
var props = shape.getProperties();
var displayPanel = document.getElementById('displayPanel');
//Create the content for the display panel based on the properties of the shape.
displayPanel.innerHTML = `<b>${props.name}</b><br/><br/>Population density: ${props.density}`;
//Show the display panel.
displayPanel.style.display = '';
}
</script>
</head>
<body onload='getMap()'>
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<div id="displayPanel" style="position:absolute;top:10px;left:10px;background:white;padding:5px;border-radius:5px;display:none;"></div>
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
<legend>Accessible shape selection</legend>
This sample shows how to add keyboard selection support to shapes by leveraging hidden popups.
To make things a bit more advanced, rather than simply displaying a popup, this sample displays the content in a custom display panel.
Use the tab key to step through the shapes on the map.
<br /><br />
Ideas to take things further;
<ul>
<li>
Sort the polygons based on their most north western coordinate.
This will make it so the tab order, when the map isn't rotated is left to right, top to bottom.'
</li>
<li>
Set a limit to the number of popup's that are created. After a couple hundred popups the page will slow down.
Additionally, users likely won't want to have to tab through hundreds of shapes.
Consider creating/removing popups after the map has been moved and only creating those that are closest to the center of the map.
</li>
<li>
Instead of highlighting the polygons by changing the color of the outline, create a highlight polygon from the bounding box of
the shape to align with how accessibility tools typically highlight elements on a page.
</li>
</ul>
</fieldset>
</body>
</html>