Skip to content

Instantly share code, notes, and snippets.

@officeofjane
Last active March 28, 2021 06:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save officeofjane/f132634f67b114815ba686484f9f7a77 to your computer and use it in GitHub Desktop.
Save officeofjane/f132634f67b114815ba686484f9f7a77 to your computer and use it in GitHub Desktop.
Date slider - histogram legend
license: mit
id date value
15 24-Nov-04 1
160 01-Mar-05 1
333 10-Mar-05 1
497 22-Mar-05 1
83 07-May-05 1
334 02-Jun-05 1
447 14-Jun-05 1
348 01-Jul-05 1
434 04-Jul-05 1
457 15-Jul-05 1
383 31-Jul-05 1
350 31-Aug-05 1
163 01-Sep-05 1
52 01-Oct-05 1
423 14-Nov-05 1
331 01-Dec-05 1
410 09-Dec-05 1
446 15-Dec-05 1
131 19-Dec-05 1
385 29-Dec-05 1
270 07-Feb-06 1
49 14-Feb-06 1
161 15-Feb-06 1
325 15-Feb-06 1
167 15-Mar-06 1
164 17-Mar-06 1
53 01-Apr-06 1
54 05-Apr-06 1
454 06-Apr-06 1
459 12-Apr-06 1
336 24-Apr-06 1
168 01-May-06 1
241 10-May-06 1
101 12-May-06 1
387 12-May-06 1
326 26-May-06 1
414 30-May-06 1
349 02-Jun-06 1
353 07-Jun-06 1
386 08-Jun-06 1
55 09-Jun-06 1
355 14-Jun-06 1
352 16-Jun-06 1
430 21-Jun-06 1
483 26-Jun-06 1
165 28-Jun-06 1
328 05-Jul-06 1
425 05-Jul-06 1
402 07-Jul-06 1
87 01-Aug-06 1
70 03-Aug-06 1
404 21-Aug-06 1
170 23-Aug-06 1
354 14-Sep-06 1
22 28-Sep-06 1
8 01-Oct-06 1
69 01-Oct-06 1
403 06-Oct-06 1
448 18-Oct-06 1
418 20-Oct-06 1
57 25-Oct-06 1
71 07-Nov-06 1
369 10-Nov-06 1
166 11-Nov-06 1
19 20-Nov-06 1
281 22-Nov-06 1
340 01-Dec-06 1
370 12-Dec-06 1
72 18-Dec-06 1
21 19-Dec-06 1
75 19-Dec-06 1
74 20-Dec-06 1
366 21-Dec-06 1
77 24-Dec-06 1
367 26-Dec-06 1
76 27-Dec-06 1
78 28-Dec-06 1
73 29-Dec-06 1
388 23-Jan-07 1
179 30-Jan-07 1
409 31-Jan-07 1
43 01-Feb-07 1
180 25-Feb-07 1
416 25-Feb-07 1
129 05-Mar-07 1
282 11-Mar-07 1
462 12-Mar-07 1
181 13-Mar-07 1
485 14-Mar-07 1
384 16-Mar-07 1
68 26-Mar-07 1
460 02-Apr-07 1
20 03-Apr-07 1
371 08-Apr-07 1
4 09-Apr-07 1
56 13-Apr-07 1
173 23-Apr-07 1
23 24-Apr-07 1
372 24-Apr-07 1
18 26-Apr-07 1
16 30-Apr-07 1
183 05-May-07 1
373 15-May-07 1
178 16-May-07 1
358 18-May-07 1
456 24-May-07 1
426 25-May-07 1
51 13-Jun-07 1
46 16-Jun-07 1
484 25-Jun-07 1
187 27-Jun-07 1
376 06-Jul-07 1
435 19-Jul-07 1
190 23-Jul-07 1
192 02-Aug-07 1
191 04-Aug-07 1
186 13-Aug-07 1
24 01-Sep-07 1
400 01-Sep-07 1
368 06-Sep-07 1
458 12-Sep-07 1
174 14-Sep-07 1
193 17-Sep-07 1
283 25-Sep-07 1
27 28-Sep-07 1
273 08-Oct-07 1
195 11-Oct-07 1
339 19-Oct-07 1
184 22-Oct-07 1
324 24-Oct-07 1
182 30-Oct-07 1
97 01-Nov-07 1
197 01-Nov-07 1
291 02-Nov-07 1
207 05-Nov-07 1
40 06-Nov-07 1
130 09-Nov-07 1
208 11-Nov-07 1
59 12-Nov-07 1
25 14-Nov-07 1
345 20-Nov-07 1
374 22-Nov-07 1
60 25-Nov-07 1
61 26-Nov-07 1
35 05-Dec-07 1
389 11-Dec-07 1
436 11-Dec-07 1
377 28-Dec-07 1
408 01-Jan-08 1
390 06-Feb-08 1
392 28-Feb-08 1
2 01-Mar-08 1
28 01-Mar-08 1
145 01-Mar-08 1
285 05-Mar-08 1
209 06-Mar-08 1
211 09-Mar-08 1
437 11-Mar-08 1
126 18-Mar-08 1
62 01-Apr-08 1
127 01-Apr-08 1
351 25-Apr-08 1
194 28-Apr-08 1
294 28-Apr-08 1
461 28-Apr-08 1
271 29-Apr-08 1
272 29-Apr-08 1
274 29-Apr-08 1
278 29-Apr-08 1
188 01-May-08 1
375 01-May-08 1
275 04-May-08 1
421 06-May-08 1
428 03-Jun-08 1
342 14-Jun-08 1
39 15-Jun-08 1
488 17-Jun-08 1
429 23-Jun-08 1
361 01-Jul-08 1
214 03-Jul-08 1
438 18-Jul-08 1
141 20-Aug-08 1
215 28-Aug-08 1
343 01-Sep-08 1
360 01-Sep-08 1
189 18-Sep-08 1
210 19-Sep-08 1
440 22-Sep-08 1
63 01-Oct-08 1
341 08-Oct-08 1
441 08-Oct-08 1
218 30-Oct-08 1
212 03-Nov-08 1
284 12-Nov-08 1
137 13-Nov-08 1
286 19-Nov-08 1
296 26-Nov-08 1
108 28-Nov-08 1
445 05-Dec-08 1
135 18-Dec-08 1
88 01-Jan-09 1
139 01-Jan-09 1
220 20-Jan-09 1
12 01-Feb-09 1
309 13-Feb-09 1
356 17-Feb-09 1
474 22-Feb-09 1
38 23-Feb-09 1
3 25-Feb-09 1
85 26-Feb-09 1
9 28-Feb-09 1
288 20-Mar-09 1
99 01-Apr-09 1
136 01-Apr-09 1
13 04-Apr-09 1
90 09-Apr-09 1
475 10-Apr-09 1
393 13-Apr-09 1
222 16-Apr-09 1
144 01-May-09 1
295 05-May-09 1
169 19-May-09 1
306 27-May-09 1
128 30-May-09 1
132 05-Jun-09 1
487 15-Jun-09 1
347 03-Jul-09 1
443 20-Jul-09 1
442 23-Jul-09 1
489 30-Jul-09 1
308 07-Aug-09 1
219 10-Aug-09 1
216 17-Aug-09 1
287 17-Aug-09 1
476 27-Aug-09 1
14 28-Aug-09 1
213 01-Sep-09 1
253 08-Sep-09 1
79 15-Sep-09 1
405 03-Oct-09 1
147 19-Oct-09 1
150 21-Oct-09 1
149 30-Oct-09 1
29 31-Oct-09 1
185 02-Nov-09 1
224 05-Nov-09 1
217 06-Nov-09 1
223 06-Nov-09 1
246 06-Nov-09 1
10 10-Nov-09 1
225 23-Nov-09 1
293 30-Nov-09 1
102 01-Dec-09 1
146 17-Dec-09 1
478 08-Feb-10 1
245 10-Feb-10 1
477 16-Feb-10 1
44 01-Mar-10 1
92 14-Mar-10 1
103 23-Mar-10 1
378 23-Mar-10 1
379 23-Mar-10 1
301 29-Mar-10 1
64 01-Apr-10 1
244 09-Apr-10 1
107 14-Apr-10 1
237 21-Apr-10 1
226 26-Apr-10 1
236 29-Apr-10 1
290 30-Apr-10 1
276 05-May-10 1
380 05-May-10 1
397 05-May-10 1
151 12-May-10 1
221 19-May-10 1
230 19-May-10 1
248 19-May-10 1
498 27-May-10 1
327 08-Jun-10 1
499 19-Jun-10 1
490 20-Jun-10 1
381 22-Jun-10 1
140 01-Jul-10 1
111 24-Aug-10 1
153 01-Sep-10 1
252 01-Sep-10 1
307 01-Sep-10 1
171 01-Oct-10 1
175 01-Oct-10 1
420 01-Oct-10 1
196 19-Oct-10 1
250 19-Oct-10 1
466 22-Oct-10 1
382 23-Oct-10 1
240 27-Oct-10 1
249 06-Nov-10 1
427 08-Nov-10 1
289 11-Nov-10 1
486 19-Nov-10 1
106 26-Nov-10 1
242 10-Dec-10 1
318 10-Dec-10 1
401 10-Dec-10 1
310 27-Dec-10 1
104 01-Jan-11 1
93 18-Jan-11 1
172 28-Jan-11 1
96 22-Feb-11 1
444 11-Mar-11 1
112 23-Mar-11 1
455 23-Mar-11 1
36 24-Mar-11 1
406 29-Mar-11 1
30 06-Apr-11 1
233 07-Apr-11 1
463 07-Apr-11 1
495 09-Apr-11 1
321 26-Apr-11 1
491 11-May-11 1
394 16-May-11 1
94 19-May-11 1
424 20-May-11 1
464 25-May-11 1
465 14-Jul-11 1
322 27-Jul-11 1
302 01-Sep-11 1
312 03-Sep-11 1
329 19-Sep-11 1
419 28-Sep-11 1
66 01-Oct-11 1
37 01-Nov-11 1
269 04-Nov-11 1
359 07-Nov-11 1
91 09-Nov-11 1
496 16-Nov-11 1
279 24-Nov-11 1
95 26-Nov-11 1
493 28-Nov-11 1
453 28-Dec-11 1
468 17-Feb-12 1
335 20-Feb-12 1
202 20-Mar-12 1
332 28-Mar-12 1
120 16-Apr-12 1
162 16-Apr-12 1
469 17-Apr-12 1
277 19-Apr-12 1
300 25-Apr-12 1
413 04-May-12 1
431 14-May-12 1
346 16-Jun-12 1
280 18-Jun-12 1
89 18-Jul-12 1
297 19-Jul-12 1
492 31-Jul-12 1
452 10-Aug-12 1
118 01-Sep-12 1
154 06-Sep-12 1
500 06-Sep-12 1
100 16-Sep-12 1
26 20-Sep-12 1
176 21-Sep-12 1
148 10-Oct-12 1
177 11-Oct-12 1
311 17-Oct-12 1
198 20-Oct-12 1
133 21-Oct-12 1
449 31-Oct-12 1
203 02-Nov-12 1
58 09-Nov-12 1
450 15-Nov-12 1
117 03-Dec-12 1
395 15-Jan-13 1
41 24-Jan-13 1
228 07-Feb-13 1
124 01-Mar-13 1
407 19-Mar-13 1
313 24-Mar-13 1
320 03-Apr-13 1
227 10-Apr-13 1
239 11-Apr-13 1
206 12-Apr-13 1
238 17-Apr-13 1
243 18-Apr-13 1
204 19-Apr-13 1
432 25-Apr-13 1
396 26-Apr-13 1
115 28-Apr-13 1
109 01-May-13 1
122 01-May-13 1
292 07-May-13 1
319 13-May-13 1
205 20-May-13 1
323 22-May-13 1
125 05-Jun-13 1
439 07-Jun-13 1
231 03-Jul-13 1
119 23-Aug-13 1
234 30-Aug-13 1
422 06-Sep-13 1
363 22-Sep-13 1
232 23-Sep-13 1
247 27-Sep-13 1
116 09-Oct-13 1
398 17-Oct-13 1
314 20-Oct-13 1
357 23-Oct-13 1
467 05-Nov-13 1
480 14-Nov-13 1
152 26-Nov-13 1
5 29-Nov-13 1
298 29-Nov-13 1
330 06-Dec-13 1
451 04-Feb-14 1
142 20-Feb-14 1
1 15-Apr-14 1
255 06-Jun-14 1
362 11-Jun-14 1
256 12-Jun-14 1
257 03-Jul-14 1
143 04-Jul-14 1
315 07-Jul-14 1
304 17-Jul-14 1
305 17-Jul-14 1
258 05-Aug-14 1
433 27-Aug-14 1
417 02-Sep-14 1
479 02-Sep-14 1
138 19-Sep-14 1
411 21-Sep-14 1
31 24-Sep-14 1
259 24-Oct-14 1
481 28-Oct-14 1
260 31-Oct-14 1
261 05-Nov-14 1
482 07-Dec-14 1
156 19-Dec-14 1
155 06-Feb-15 1
134 01-Mar-15 1
254 10-Apr-15 1
262 18-May-15 1
471 22-May-15 1
263 01-Jun-15 1
337 29-Jun-15 1
86 20-Aug-15 1
316 02-Sep-15 1
48 10-Sep-15 1
473 19-Sep-15 1
344 21-Sep-15 1
11 01-Oct-15 1
364 11-Nov-15 1
494 26-Nov-15 1
105 24-Jun-16 1
123 01-Sep-16 1
365 06-Oct-16 1
82 22-Oct-16 1
399 13-Dec-16 1
42 26-Dec-16 1
317 16-Feb-17 1
34 24-Mar-17 1
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body {
font-family:"avenir next", Arial, sans-serif;
font-size: 12px;
color: #696969;
}
.ticks {
font-size: 10px;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
.track {
stroke: #dcdcdc;
stroke-width: 10px;
}
.track-inset {
stroke: #dcdcdc;
stroke-width: 8px;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
stroke: transparent;
cursor: crosshair;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
}
</style>
</head>
<body>
<div id="vis"></div>
<script>
var margin = {top:50, right:50, bottom:0, left:50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var histHeight = height/5;
var parseDate = d3.timeParse("%d-%b-%y");
var formatDateIntoYear = d3.timeFormat("%Y");
var startDate = new Date("2004-11-01"),
endDate = new Date("2017-04-01");
var dateArray = d3.timeYears(startDate, d3.timeYear.offset(endDate, 1));
var colours = d3.scaleOrdinal()
.domain(dateArray)
.range(['#ffc388','#ffb269','#ffa15e','#fd8f5b','#f97d5a','#f26c58','#e95b56','#e04b51','#d53a4b','#c92c42','#bb1d36','#ac0f29','#9c0418','#8b0000']);
// x scale for time
var x = d3.scaleTime()
.domain([startDate, endDate])
.range([0, width])
.clamp(true);
// y scale for histogram
var y = d3.scaleLinear()
.range([histHeight, 0]);
////////// histogram set up //////////
// set parameters for histogram
var histogram = d3.histogram()
.value(function(d) { return d.date; })
.domain(x.domain())
.thresholds(x.ticks(d3.timeYear));
var svg = d3.select("#vis")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var hist = svg.append("g")
.attr("class", "histogram")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
////////// plot set up //////////
var dataset;
var plot = svg.append("g")
.attr("class", "plot")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
////////// load data //////////
d3.csv("histogram.csv", prepare, function(data) {
// group data for bars
var bins = histogram(data);
// y domain based on binned data
y.domain([0, d3.max(bins, function(d) { return d.length; })]);
var bar = hist.selectAll(".bar")
.data(bins)
.enter()
.append("g")
.attr("class", "bar")
.attr("transform", function(d) {
return "translate(" + x(d.x0) + "," + y(d.length) + ")";
});
bar.append("rect")
.attr("class", "bar")
.attr("x", 1)
.attr("width", function(d) { return x(d.x1) - x(d.x0) - 1; })
.attr("height", function(d) { return histHeight - y(d.length); })
.attr("fill", function(d) { return colours(d.x0); });
bar.append("text")
.attr("dy", ".75em")
.attr("y", "6")
.attr("x", function(d) { return (x(d.x1) - x(d.x0))/2; })
.attr("text-anchor", "middle")
.text(function(d) { if (d.length>15) { return d.length; } })
.style("fill", "white");
dataset = data;
drawPlot(dataset);
})
////////// slider //////////
var currentValue = 0;
var slider = svg.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + margin.left + "," + (margin.top+histHeight+5) + ")");
slider.append("line")
.attr("class", "track")
.attr("x1", x.range()[0])
.attr("x2", x.range()[1])
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-inset")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-overlay")
.call(d3.drag()
.on("start.interrupt", function() { slider.interrupt(); })
.on("start drag", function() {
currentValue = d3.event.x;
update(x.invert(currentValue));
})
);
slider.insert("g", ".track-overlay")
.attr("class", "ticks")
.attr("transform", "translate(0," + 18 + ")")
.selectAll("text")
.data(x.ticks(10))
.enter()
.append("text")
.attr("x", x)
.attr("y", 10)
.attr("text-anchor", "middle")
.text(function(d) { return formatDateIntoYear(d); });
var handle = slider.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 9);
function drawPlot(data) {
var locations = plot.selectAll(".location")
.data(data, function(d) { return d.id; });
// if filtered dataset has more circles than already existing, transition new ones in
locations.enter()
.append("circle")
.attr("class", "location")
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return Math.random()*((height/2+50)-(height/2-50))+(height/2-50); })
.style("fill", function(d) { return colours(d3.timeYear(d.date)); })
.style("stroke", function(d) { return colours(d3.timeYear(d.date)); })
.style("opacity", 0.3)
.attr("r", 5)
.transition()
.duration(400)
.attr("r", 15)
.transition()
.attr("r", 5);
// if filtered dataset has less circles than already existing, remove excess
locations.exit()
.remove();
}
function update(h) {
handle.attr("cx", x(h));
// filter data set and redraw plot
var newData = dataset.filter(function(d) {
return d.date < h;
})
drawPlot(newData);
// histogram bar colours
d3.selectAll(".bar")
.attr("fill", function(d) {
if (d.x0 < h) {
return colours(d.x0);
} else {
return "#eaeaea";
}
})
}
function prepare(d) {
d.date = parseDate(d.date);
d.value = +d.value;
return d;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment