-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.html
380 lines (371 loc) · 24.3 KB
/
index.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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8" />
<link rel="icon" href="resources/favicon.svg" />
<title>ODI Leeds Hexmap Library</title>
<script src="odi.hexmap.js"></script>
<script src="resources/highlight.pack.js"></script>
<link rel="StyleSheet" href="resources/highlight.css" type="text/css" />
<style>
/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; }
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
body { line-height: 1em; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
table { border-collapse: collapse; border-spacing: 0; }
/* apply a natural box layout model to all elements */
*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
/* End of reset */
/* Main site styling */
body {
background-color: #000000;
font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
font-size: 16px;
color: #efefef;
margin: 0px;
padding: 0px;
line-height: 1.44em;
text-rendering: optimizeLegibility;
}
#main { background-color: #ffffff; color: #333333; }
.holder { position: relative; width: 1080px; max-width: 100%; margin: auto; }
.padded { padding: 1em; }
h1 { font-size: 1.7em; margin-top: 1em; font-weight: 600; margin: 0; }
h2 { font-size: 1.7em; margin-top: 1.7647058823529411em; font-weight: 500; }
h3 { font-size: 1.4em; margin-top: 1.428571em; }
h1:first-child, h2:first-child, h3:first-child { margin-top: 0; }
footer { width: 100%; padding: 1em; padding-bottom: 3em; }
footer a, footer a:visited { color: inherit; }
code, pre { font-family: monospace; color: #555555; background-color: #efefef; padding: 0.125em 0.25em; }
button, .button { border: 0px; font-size: 1em; background-color: #efefef; color: black; text-decoration: none!important; display: inline-block; padding: 0.5em 1em; cursor: pointer; vertical-align: top; line-height: 1.25em; }
.prettyprint {
background: #efefef;
padding: 1em;
}
section.example {
border-top: 1px solid #999;
margin-top: 4em;
padding-top: 4em;
}
h2 + *, h3 + * { margin-top: 1em; }
h4 { margin-top: 1em; font-weight: bold; }
p { margin-top: 1em; }
p + div { margin-top: 2em; }
section.example h2 + * { margin-top: 1em; }
.howto { margin-top: 1em; }
.b1-bg, footer { background: black; color: white; }
.b6-bg { background: white; color: black; }
#intro { text-align: center; padding: 1em; max-width: 720px; margin: 0 auto 1em; }
figure figcaption {
width: 70%;
margin: 1em auto 0 auto;
font-size: 0.8em;
line-height: 1.2em;
text-align: center;
color: #999;
}
figure:hover figcaption { color: inherit; }
</style>
</head>
<body class="b6-bg">
<div class="padded c14-bg" style="text-align:center;color: rgb(95, 82, 7);
background-color: rgb(251, 245, 208);">This repo has been superceded by one at <a href="https://open-innovations.github.io/oi.hexmap.js/">oi.hexmap.js</a>. Please update your links.</div>
<header>
<div class="b1-bg padded">
<div class="holder" style="text-align:center;">
<a href="https://odileeds.org/" aria-label="ODI Leeds">
<svg version="1.1" viewBox="0 0 250 91" width="250" height="91" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<g transform="translate(0,-961.4)">
<circle cx="65.42" cy="1006.6" r="15.714" fill-opacity=".5"/>
<rect x="87.92" y="1001.7" width="35.179" height="10" fill-opacity=".5"/>
<path d="m86.07 966.9c-2.1 0.15-3.94 0.56-6.06 0.7 0.92 8.34 2.24 17.03 3.38 25.73-3.07-6.04-5.86-12.38-8.96-18.39-1.91 0.77-3.63 1.73-5.48 2.56 2.9 6.1 5.89 12.12 8.74 18.28 0.14 0 0.1 0.17 0 0-4-3.96-7.74-8.18-11.76-12.11-1.58 1.26-2.862 2.81-4.428 4.07 1.016 1.14 2.056 2.25 3.108 3.36h0.72c8.53 0 15.44 6.95 15.44 15.5 0 8.6-6.93 15.5-15.44 15.5-1.13 0-2.251-0.1-3.349-0.4-3.266 1.6-6.509 3.1-9.68 4.8 0.877 1.8 1.828 3.5 2.563 5.5 5.877-2.8 11.976-5.9 17.696-8.4-0.15 0.6-1.89 1.2-1.86 1.9 0 0 0.87 0.8 1.05 1 1.04 1.1 2.4 2.6 3.26 3.3 0.69-0.6 1.31-1.3 1.98-1.9-0.81 1.6-1.71 3.2-2.56 4.8 1.8 1 3.57 2 5.47 2.9 1.24-2.4 2.54-4.8 3.84-7.1 0-0.1 0-0.2 0.12-0.2 0 0 0 0.2-0.12 0.2-0.84 5.6-2.05 10.9-2.91 16.5 2.08 0.3 4 0.8 6.06 1.1 0.66-3.8 1.28-7.7 2.09-11.3 0.1 1.2 0.24 1.7 0.35 2.9 2.03-0.3 4.08-0.5 6.06-0.8-0.1-2-0.73-4-0.59-5.7 2.4 5.3 5.03 10.4 7.46 15.7 1.98-0.8 3.83-1.7 5.59-2.7-2.6-5.2-5.09-10.4-7.57-15.7-0.14 0-0.1-0.2 0 0 4.66 4.6 9.02 9.6 13.74 14.2 1.55-1.3 2.96-2.8 4.42-4.2-4.52-4.6-9.3-9.6-13.51-14.2 0.75 0.3 1.28 0.8 2.1 1 1.03-1.7 1.99-3.5 2.91-5.3-0.71-0.5-1.56-0.8-2.21-1.3 2.16 0.4 4.32 0.8 6.52 1.2 0.3-2.1 0.73-4 1.05-6.1-2.1-0.4-4.49-0.5-6.29-1.3 3.84-0.4 7.63-0.9 11.41-1.4h-32.51v-9.1h28.21c-0.84-1.7-1.57-3.42-2.45-5.03-2.66 1.26-5.35 2.49-7.92 3.83-0.1-0.4 0.42-0.8 0.7-1.03 5.31-5.2 11.31-10.6 16.65-15.85-1.18-1.72-2.8-3.01-4.19-4.53-5.91 5.7-11.84 11.37-17.82 17 0 0.14-0.17 0.1 0 0 3.24-6.2 6.59-12.28 9.9-18.4-1.65-1.14-3.63-1.96-5.36-3.02-2.9 5.32-5.85 10.6-8.61 16.06 0.17-2.26 0.84-5.05 1.28-7.45-1.89-0.48-3.99-0.75-5.94-1.16-1.03 4.1-1.69 8.56-2.45 12.92-1.44-9.51-2.68-19.11-3.84-28.41zm-37.376 34.8c-0.605 1.6 0.114 3.8-0.408 5.5v0.7c0.822 0.1 0.88 0.2 1.701 0.3-0.06-0.5-0.1-1.1-0.108-1.6 0-1.5 0.235-3 0.68-4.5-0.619-0.2-1.25-0.3-1.865-0.4zm80.696 2c-1.88 0.2-3.74 0.4-5.59 0.7v6.2c2.1-0.3 3.68-0.7 5.78-1v-1c-0.32-1.6 0-3.2-0.19-4.9zm-75.927 12.8c0.156 1.2 0.308 2.4 0.469 3.5 1.004-0.1 2.015-0.2 3.028-0.4-1.315-0.8-2.494-1.9-3.497-3.1z" clip-rule="evenodd" fill="#67E767" fill-rule="evenodd"/>
<path d="m65.39 989.07c-4.711 0-9.141 1.84-12.473 5.17-3.333 3.33-5.168 7.76-5.168 12.46s1.835 9.1 5.168 12.5c3.332 3.3 7.762 5.1 12.473 5.1 4.71 0 9.14-1.8 12.48-5.1 1.72-1.7 3.03-3.8 3.91-6v10.9h14.98c2.59 0 5.02-0.4 7.22-1.3 2.17-0.8 4.07-2 5.66-3.5 1.77-1.7 3.08-3.7 3.92-6v10.8h16.52v-34.76h-16.52v10.76c-0.84-2.29-2.15-4.34-3.92-6.03-1.58-1.52-3.49-2.7-5.66-3.51-2.2-0.82-4.63-1.23-7.22-1.23h-14.98v10.87c-0.88-2.22-2.19-4.24-3.91-5.96-3.34-3.33-7.77-5.17-12.48-5.17zm0 2.82c8.19 0 14.82 6.64 14.82 14.81 0 8.2-6.63 14.8-14.82 14.8-8.186 0-14.821-6.6-14.821-14.8 0-8.17 6.635-14.81 14.821-14.81zm-3.093 10.81c-0.588 0-1.057 0.1-1.404 0.3-0.349 0.2-0.614 0.5-0.799 0.8-0.186 0.4-0.309 0.8-0.359 1.3s-0.08 1-0.08 1.6 0.02 1.2 0.08 1.7c0.05 0.4 0.174 0.9 0.359 1.2 0.185 0.4 0.448 0.7 0.799 0.8 0.346 0.2 0.815 0.3 1.404 0.3 0.586 0 1.053-0.1 1.403-0.3 0.35-0.1 0.62-0.4 0.8-0.8 0.19-0.3 0.3-0.8 0.36-1.2 0-0.5 0.1-1.1 0.1-1.7s0-1.1-0.1-1.6-0.17-0.9-0.36-1.3c-0.18-0.3-0.45-0.6-0.8-0.8s-0.817-0.3-1.403-0.3zm-9.379 0.1v7.8h1.436v-5.4h0.02l1.916 5.4h1.785v-7.8h-1.438v5.4h-0.02l-1.895-5.4h-1.807zm13.672 0v7.8h2.47c0.53 0 0.96-0.1 1.3-0.2 0.34-0.2 0.61-0.4 0.81-0.8 0.21-0.3 0.33-0.7 0.43-1.2 0.13-0.5 0.13-1.1 0.13-1.8 0-0.6 0-1.1-0.1-1.5-0.1-0.5-0.19-0.9-0.37-1.2-0.19-0.4-0.45-0.6-0.78-0.8-0.34-0.2-0.77-0.3-1.32-0.3zm6.82 0v7.8h4.45v-1.3h-2.88v-2.1h2.61v-1.3h-2.61v-1.8h2.78v-1.3zm-11.113 1c0.231 0 0.419 0.1 0.559 0.2 0.141 0.1 0.246 0.3 0.326 0.5 0.07 0.2 0.124 0.5 0.154 0.9s0.04 0.8 0.04 1.3-0.01 1-0.04 1.4c-0.03 0.3-0.07 0.6-0.154 0.8-0.08 0.3-0.184 0.4-0.326 0.5-0.14 0.2-0.328 0.2-0.559 0.2-0.235 0-0.419 0-0.56-0.2-0.143-0.1-0.248-0.2-0.328-0.5-0.07-0.2-0.133-0.5-0.153-0.8-0.03-0.4-0.04-0.9-0.04-1.4s0-0.9 0.04-1.3c0.02-0.4 0.07-0.7 0.153-0.9 0.08-0.2 0.185-0.4 0.328-0.5 0.141-0.1 0.326-0.2 0.56-0.2zm5.863 0.2h0.66c0.3 0 0.54 0 0.72 0.2 0.17 0.1 0.3 0.2 0.4 0.5 0.1 0.2 0.18 0.5 0.18 0.8v1.2 1.3c0 0.3-0.1 0.6-0.19 0.8-0.1 0.3-0.23 0.4-0.4 0.5s-0.39 0.2-0.66 0.2h-0.7v-5.5z" fill="#fff"/>
<g fill="#fff" stroke-width="1px">
<path d="m140.66 999.78v13.82h9.78v-2.5h-6.74v-11.32h-3.04z"/>
<path d="m152.12 999.78v13.82h10.5v-2.5h-7.46v-3.4h6.71v-2.4h-6.71v-3h7.31v-2.52h-10.35z"/>
<path d="m164.65 999.78v13.82h10.5v-2.5h-7.46v-3.4h6.7v-2.4h-6.7v-3h7.3v-2.52h-10.34z"/>
<path d="m180.22 1011.1v-8.8h2.17q1.12 0 1.88 0.4 0.77 0.3 1.24 0.9 0.46 0.6 0.65 1.4 0.22 0.9 0.22 1.9 0 1.2-0.29 1.9-0.29 0.8-0.78 1.3-0.48 0.5-1.1 0.7-0.62 0.3-1.28 0.3h-2.71zm-3.05-11.32v13.82h5.97q1.59 0 2.75-0.5 1.18-0.6 1.96-1.5 0.79-0.9 1.18-2.2t0.39-2.8q0-1.7-0.49-3-0.46-1.3-1.31-2.1-0.84-0.9-2-1.3-1.14-0.42-2.48-0.42h-5.97z"/>
<path d="m193.55 1009h-2.94q-0 1.3 0.46 2.2 0.49 1 1.3 1.6 0.83 0.6 1.9 0.8 1.08 0.3 2.23 0.3 1.41 0 2.48-0.3 1.08-0.3 1.8-0.9 0.73-0.6 1.1-1.4t0.37-1.8q0-1.2-0.5-1.9-0.49-0.8-1.17-1.2-0.67-0.4-1.37-0.6-0.68-0.2-1.07-0.3-1.29-0.4-2.11-0.6-0.79-0.2-1.26-0.4-0.44-0.2-0.6-0.5-0.15-0.2-0.15-0.6 0-0.5 0.19-0.8 0.19-0.2 0.48-0.4 0.31-0.2 0.68-0.3t0.74-0.1q0.56 0 1.03 0.1 0.48 0.1 0.85 0.3 0.37 0.3 0.58 0.7 0.23 0.4 0.27 1h2.95q0-1.2-0.47-2-0.44-0.9-1.22-1.4-0.77-0.57-1.78-0.8-0.99-0.25-2.08-0.25-0.93 0-1.86 0.25t-1.66 0.8q-0.74 0.5-1.2 1.3-0.45 0.8-0.45 1.8t0.35 1.7q0.37 0.6 0.95 1.1 0.58 0.4 1.32 0.7 0.73 0.3 1.51 0.5 0.75 0.2 1.49 0.4 0.74 0.1 1.32 0.4 0.58 0.2 0.93 0.5 0.37 0.4 0.37 1 0 0.5-0.28 0.8-0.27 0.4-0.67 0.5-0.41 0.2-0.88 0.3-0.46 0.1-0.87 0.1-0.6 0-1.16-0.2-0.56-0.1-0.99-0.4-0.4-0.3-0.66-0.8-0.25-0.5-0.25-1.2z"/>
</g>
</g>
</svg></a>
<h1>Hexmap Library</h1>
<script>
a = new ODI.hexmap();
document.querySelector('h1').innerHTML += ' v'+a.version+'';
</script>
</div>
</div>
</header>
<div class="padded">
<div class="holder">
<p id="intro"><a href="odi.hexmap.js">odi.hexmap.js</a> (20kB; <a href="odi.hexmap.min.js">12kB minified</a>; 5kB minified+gzipped) is our small, standalone, Javascript library for making interactive hexmaps (cartograms). There are some <a href="#ex1">examples below</a>.</p>
<p>This library assumes you have an existing hex layout as <a href="https://odileeds.org/projects/hexmaps/hexjson">HexJSON</a> (e.g. <a href="https://github.com/odileeds/hexmaps/tree/gh-pages/maps">layouts we've made</a>) and the ability to add Javascript to a webpage. The library creates an SVG (scalable vector graphic) of hexes - which can be styled via CSS - and some basic event callbacks.</p>
<style>
#hero {
width: 100%;
margin-top: 200px;
margin-top: 1em;
overflow: hidden;
}
</style>
<div id="hero">
</div>
<script>
c = ["#2254F4","#178CFF","#00B6FF","#08DEF9","#1DD3A7","#0DBC37","#67E767","#722EA5","#E6007C","#EF3AAB","#D73058","#D60303","#FF6700","#F9BC26"];
// Create a HexJSON to fill the space
hexjson = {"layout":"odd-r","hexes":{}};
for(q = 0; q<22; q++){
for(r = 0; r<5;r++) hexjson.hexes[q+"-"+r] = {"n":q+","+r,"q":q,"r":r,"colour":c[Math.round(Math.random()*14)]};
}
hero = new ODI.hexmap(document.getElementById('hero'),{
"hexjson": hexjson,
"size": 32 // Hard-code a size for the hexes
});
</script>
<section class="example" id="ex1">
<h2>A basic hexmap</h2>
<p>Let's create a very basic hex map using a HexJSON layout. Everything happens in <code>ODI.hexmap(el,attributes)</code> where <code>el</code> is the DOM element we are attaching the hex map to and <code>attributes</code> defines properties of the hex map. At a minimum, <code>attributes</code> should include <code>hexjson</code> which can either be inline HexJSON or a path to an external HexJSON file. In this example we will add the HexJSON inline.</p>
<p>By default, the <code>title</code> of each hex (try hovering over them) uses the <code>n</code> or <code>name</code> property of the hex in the HexJSON.</p>
<div class="example-code">
<style>
/* Define the size of the hexmap area */
#hexmap1 { height: 300px; width: 100%; }
</style>
<div id="hexmap1"></div>
<script>
ODI.ready(function(){
// Attach our hexmap to <div id="hexmap1"></div>
hex = new ODI.hexmap(document.getElementById('hexmap1'),{
'labels': { 'show': true },
// Define the HexJSON - https://odileeds.org/projects/hexmaps/hexjson
'hexjson':{
"layout":"odd-r",
"hexes": {
"A":{"n":"0,1","q":0,"r":1},
"B":{"n":"1,1","q":1,"r":1},
"C":{"n":"2,1","q":2,"r":1},
"D":{"n":"0,2","q":0,"r":2},
"E":{"n":"1,2","q":1,"r":2},
"F":{"n":"2,2","q":2,"r":2}
}
}
});
});
</script>
</div>
</section>
<section class="example" id="ex2">
<h2>Styling hexes and labels</h2>
<p>We will use the same hexmap but this time we add some extra properties to each item in the HexJSON. The <code>colour</code> property is used to colour each hex. We also turn on labels, make sure they are clipped to the hexagon, and customise the text of the label. The default label text is the value of <code>n</code> but we can provide a <code>format</code> function to customise the content. Here we split the string into separate <code>tspan</code> elements and add the population value. We make use of CSS classes so that we can make some parts of the label only visible on hover and even scale the size of the hexagon on hover (the code adds the style <code>.hover</code> to the hexagon and label).</p>
<div class="example-code">
<style>
#hexmap2 { height: 500px; width: 100%; animation-duration: 0.3s; }
#hexmap2 .hex-cell { stroke: white; stroke-width: 2; transition: fill 0.3s ease-in, stroke 0.3s ease-in, stroke-width 0.3s ease-in; }
/* Make the hexagon larger when hovered */
#hexmap2 .hex-cell.hover { stroke-width: 4px; transform: scale(1.75); }
/* Set the on and off styles for the text labels */
#hexmap2 .hex-label tspan.on { display: none; }
#hexmap2 .hex-label tspan.off { display: block; }
#hexmap2 .hex-label tspan.big { font-weight: bold; font-size: 1.2em; }
#hexmap2 .hex-label.hover tspan.on { display: block; }
#hexmap2 .hex-label.hover tspan.off { display: none; }
</style>
<figure>
<div id="hexmap2"></div>
<figcaption>Cartogram showing Leeds wards with coloured assigned manually.</figcaption>
</figure>
<script>
ODI.ready(function(){
hex = new ODI.hexmap(document.getElementById('hexmap2'),{
'label':{
'show': true, // Show a label
'clip': true, // Make sure the label is clipped to the hexagon
// Define a function to format the hex labels
// It is passed:
// * txt - a text string with the hex's name
// * attr - an object containing:
// .* size - the size in pixels
// .* font-size - the font size in pixels
// .* x - the horizontal position in pixels
// .* y - the vertical position in pixels
// .* hex - the hexagon's HexJSON properties
'format': function(txt,attr){
tspans = '<tspan class="off">'+txt.substr(0,3)+'</tspan>';
lines = txt.split(/ /);
lines.push(attr.hex.pop.toLocaleString());
for(var i = 0; i < lines.length; i++){
tspans += '<tspan class="on'+(i==lines.length-1 ? ' big':'')+'" y="'+(attr.y + (i-lines.length/2+0.5)*attr['font-size'])+'" x="'+attr.x+'">'+lines[i]+'</tspan>';
}
return tspans;
}
},
// The HexJSON layout
'hexjson':{
"layout":"odd-r",
"hexes": {
"E05001425":{"n":"Guiseley and Rawdon","q":-3,"r":3,"pop":18253,"colour":"rgb(247, 171, 45)"},
"E05001437":{"n":"Otley and Yeadon","q":-2,"r":3,"pop":17616,"colour":"rgb(246, 166, 47)"},
"E05001411":{"n":"Adel and Wharfedale","q":-1,"r":3,"pop":15919,"colour":"rgb(248, 186, 38)"},
"E05001412":{"n":"Alwoodley","q":0,"r":3,"pop":17890,"colour":"rgb(245, 150, 55)"},
"E05001426":{"n":"Harewood","q":1,"r":3,"pop":15194,"colour":"rgb(249, 188, 38)"},
"E05001443":{"n":"Wetherby","q":2,"r":3,"pop":15753,"colour":"rgb(247, 172, 45)"},
"E05001428":{"n":"Horsforth","q":-2,"r":2,"pop":17318,"colour":"rgb(247, 172, 45)"},
"E05001442":{"n":"Weetwood","q":-1,"r":2,"pop":15777,"colour":"rgb(246, 160, 50)"},
"E05001434":{"n":"Moortown","q":0,"r":2,"pop":17595,"colour":"rgb(246, 161, 50)"},
"E05001440":{"n":"Roundhay","q":1,"r":2,"pop":17419,"colour":"rgb(247, 170, 45)"},
"E05001418":{"n":"Calverley and Farsley","q":-4,"r":1,"pop":18009,"colour":"rgb(245, 150, 54)"},
"E05001416":{"n":"Bramley and Stanningley","q":-3,"r":1,"pop":16582,"colour":"rgb(236, 61, 95)"},
"E05001432":{"n":"Kirkstall","q":-2,"r":1,"pop":15547,"colour":"rgb(239, 91, 82)"},
"E05001427":{"n":"Headingley and Hyde Park","q":-1,"r":1,"pop":19339,"colour":"rgb(230, 9, 119)"},
"E05001419":{"n":"Chapel Allerton","q":0,"r":1,"pop":17792,"colour":"rgb(241, 117, 70)"},
"E05001430":{"n":"Killingbeck and Seacroft","q":1,"r":1,"pop":16467,"colour":"rgb(233, 36, 107)"},
"E05001438":{"n":"Pudsey","q":-3,"r":0,"pop":18485,"colour":"rgb(244, 139, 60)"},
"E05001414":{"n":"Armley","q":-2,"r":0,"pop":16270,"colour":"rgb(235, 54, 99)"},
"E05001429":{"n":"Little London and Woodhouse","q":-1,"r":0,"pop":14367,"colour":"rgb(230, 0, 124)"},
"E05001424":{"n":"Gipton and Harehills","q":0,"r":0,"pop":16350,"colour":"rgb(235, 58, 97)"},
"E05001421":{"n":"Cross Gates and Whinmoor","q":1,"r":0,"pop":17819,"colour":"rgb(239, 91, 81)"},
"E05001422":{"n":"Farnley and Wortley","q":-3,"r":-1,"pop":17908,"colour":"rgb(237, 73, 90)"},
"E05001415":{"n":"Beeston and Holbeck","q":-2,"r":-1,"pop":15203,"colour":"rgb(235, 54, 98)"},
"E05001420":{"n":"Hunslet and Riverside","q":-1,"r":-1,"pop":17054,"colour":"rgb(236, 68, 92)"},
"E05001417":{"n":"Burmantofts and Richmond Hill","q":0,"r":-1,"pop":15522,"colour":"rgb(235, 52, 100)"},
"E05001441":{"n":"Temple Newsam","q":1,"r":-1,"pop":16437,"colour":"rgb(240, 106, 75)"},
"E05001435":{"n":"Morley North","q":-2,"r":-2,"pop":17733,"colour":"rgb(241, 109, 73)"},
"E05001433":{"n":"Middleton Park","q":-1,"r":-2,"pop":19135,"colour":"rgb(234, 44, 103)"},
"E05001439":{"n":"Rothwell","q":0,"r":-2,"pop":15889,"colour":"rgb(243, 133, 62)"},
"E05001423":{"n":"Garforth and Swillington","q":1,"r":-2,"pop":16260,"colour":"rgb(247, 170, 45)"},
"E05001436":{"n":"Morley South","q":-2,"r":-3,"pop":16684,"colour":"rgb(239, 93, 81)"},
"E05001413":{"n":"Ardsley and Robin Hood","q":-1,"r":-3,"pop":17443,"colour":"rgb(239, 97, 79)"},
"E05001431":{"n":"Kippax and Methley","q":0,"r":-3,"pop":16355,"colour":"rgb(242, 118, 69)"}
}
}
});
});
</script>
</div>
</section>
<section class="example" id="ex3">
<h2>Using external data and adding tooltips</h2>
<p>This example loads in an external HexJSON file, loads in some data, and then colours the hexes depending on the data. To work out the colours we'll make a little helper function <code>ColourScale</code>.</p>
<div class="example-code">
<style>
#hexmap3 { height: 800px; width: 100%; margin-top: 1em; position: relative; animation-duration: 0.3s; }
#hexmap3 .hex-cell { stroke: black; stroke-width: 0; transition: fill 0.2s ease-in, stroke 0.2s ease-in, stroke-width 0.2s ease-in; }
#hexmap3 .hex-cell.hover { stroke-width: 4px; }
@media only screen and (max-width: 700px) {
/* Don't bother with labels if it is too small */
#hexmap3 .hex-label { display: none; }
}
#hexmap3 .tooltip { position: absolute; text-align: center; background: black; color: white; padding: 0.25em 0.5em; transform: translate3d(-50%,50%,0); transition: left 0.1s linear, top 0.1s linear; border-radius: 4px; }
#hexmap3 .tooltip::after { content: ""; position: absolute; bottom: auto; width: 0; height: 0; border: 0.5em solid transparent; left: 50%; top: 0%; transform: translate3d(-50%,-100%,0); border-color: transparent; border-bottom-color: black; }
</style>
<figure>
<div id="hexmap3"></div>
<figcaption>Cartogram showing UK constituencies coloured by the number of signatures they received on House of Commons petitions during 2017-2019. Data from The House of Commons Library. Layout by ODI Leeds and contributors.</figcaption>
</figure>
<script>
ODI.ready(function(){
// Define a colour scale helper function
function ColourScale(c){
var s,n;
s = c;
n = s.length;
// Get a colour given a value, and the range minimum/maximum
this.getValue = function(v,min,max){
var c,a,b;
v = (v-min)/(max-min);
if(v<0) return 'rgb('+s[0].rgb.join(',')+')';
if(v>=1) return 'rgb('+s[n-1].rgb.join(',')+')';
for(c = 0; c < n-1; c++){
a = s[c];
b = s[c+1];
if(v >= a.v && v < b.v){
pc = Math.min(1,(v - a.v)/(b.v-a.v));
rgb = [Math.round(a.rgb[0] + (b.rgb[0]-a.rgb[0])*pc),Math.round(a.rgb[1] + (b.rgb[1]-a.rgb[1])*pc),Math.round(a.rgb[2] + (b.rgb[2]-a.rgb[2])*pc)];
return 'rgb('+rgb.join(',')+')';
}
}
};
return this;
}
// Define the Viridis colour scale
viridis = new ColourScale([{'rgb':[68,1,84],v:0},{'rgb':[72,35,116],'v':0.1},{'rgb':[64,67,135],'v':0.2},{'rgb':[52,94,141],'v':0.3},{'rgb':[41,120,142],'v':0.4},{'rgb':[32,143,140],'v':0.5},{'rgb':[34,167,132],'v':0.6},{'rgb':[66,190,113],'v':0.7},{'rgb':[121,209,81],'v':0.8},{'rgb':[186,222,39],'v':0.9},{'rgb':[253,231,36],'v':1}]);
// Create the hexagon layout
hex = new ODI.hexmap(document.getElementById('hexmap3'),{
// The HexJSON layout
'hexjson':'resources/constituencies.hexjson',
// Once we've loaded the map the ready function is called
'ready':function(){
// Load the data
ODI.ajax('resources/2017-9.json',{
'this': this, // Set the context to the hexmap
'dataType':'json',
'success':function(data){
// Process the data file to find the minimum and maximum
var min = 1e100;
var max = -1e100;
for(var r in data){
min = Math.min(data[r],min);
max = Math.max(data[r],max);
}
this.data = data;
// Update the hex colours
this.updateColours(function(r){ return viridis.getValue(data[r],min,max); });
},
'error':function(e,attr){ this.log('ERROR','Unable to load ',attr.url,attr); }
});
}
});
// Make a tooltip
hex.on('mouseover',function(e){
var svg,tip,bb,bbo,hex;
svg = e.data.hexmap.el;
hex = e.target;
// Get any existing tooltip for this hexmap
tip = svg.querySelector('.tooltip');
if(!tip){
// Add a new tooltip
tip = document.createElement('div');
tip.classList.add('tooltip');
svg.appendChild(tip);
}
// Update contents of tooltip
tip.innerHTML = e.data.data.n+'<br />'+e.data.hexmap.data[e.data.region].toLocaleString()+' signatures';
// Update position of tooltip
bb = hex.getBoundingClientRect();
bbo = svg.getBoundingClientRect();
tip.style.left = Math.round(bb.left + bb.width/2 - bbo.left + svg.scrollLeft)+'px';
tip.style.top = Math.round(bb.top + bb.height/2 - bbo.top)+'px';
});
});
</script>
</div>
</section>
</div>
</div>
<footer>
<div class="holder">
<p>© 2021 <a href="https://odileeds.org/" target="_parent">ODI Leeds</a> (<a href="https://creativecommons.org/licenses/by/4.0/" target="_parent">CC BY</a>). Find the <a href="https://github.com/odileeds/odi.hexmap.js">code on Github</a>.</p>
</div>
</footer>
<script src="resources/odi.formatexamples.js"></script>
<script src="https://odileeds.org/resources/odi.log.js"></script>
<script>
ODI.log.setup({'id':'odileeds','target':['odileeds.github.io']}).add('action=view');
</script>
</body>
</html>