Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Timeline using d3.js
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Chronological Diagram of Asia</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js"></script>
<style type="text/css">
.chart {
shape-rendering: crispEdges;
}
.mini text {
font: 9px sans-serif;
}
.main text {
font: 12px sans-serif;
}
.miniItem0 {
fill: darksalmon;
stroke-width: 6;
}
.miniItem1 {
fill: darkolivegreen;
fill-opacity: .7;
stroke-width: 6;
}
.miniItem2 {
fill: slategray;
fill-opacity: .7;
stroke-width: 6;
}
.brush .extent {
stroke: gray;
fill: dodgerblue;
fill-opacity: .365;
}
</style>
</head>
<body>
<script type="text/javascript">
//data
var lanes = ["Chinese","Japanese","Korean"],
laneLength = lanes.length,
items = [{"lane": 0, "id": "Qin", "start": 5, "end": 205},
{"lane": 0, "id": "Jin", "start": 265, "end": 420},
{"lane": 0, "id": "Sui", "start": 580, "end": 615},
{"lane": 0, "id": "Tang", "start": 620, "end": 900},
{"lane": 0, "id": "Song", "start": 960, "end": 1265},
{"lane": 0, "id": "Yuan", "start": 1270, "end": 1365},
{"lane": 0, "id": "Ming", "start": 1370, "end": 1640},
{"lane": 0, "id": "Qing", "start": 1645, "end": 1910},
{"lane": 1, "id": "Yamato", "start": 300, "end": 530},
{"lane": 1, "id": "Asuka", "start": 550, "end": 700},
{"lane": 1, "id": "Nara", "start": 710, "end": 790},
{"lane": 1, "id": "Heian", "start": 800, "end": 1180},
{"lane": 1, "id": "Kamakura", "start": 1190, "end": 1330},
{"lane": 1, "id": "Muromachi", "start": 1340, "end": 1560},
{"lane": 1, "id": "Edo", "start": 1610, "end": 1860},
{"lane": 1, "id": "Meiji", "start": 1870, "end": 1900},
{"lane": 1, "id": "Taisho", "start": 1910, "end": 1920},
{"lane": 1, "id": "Showa", "start": 1925, "end": 1985},
{"lane": 1, "id": "Heisei", "start": 1990, "end": 1995},
{"lane": 2, "id": "Three Kingdoms", "start": 10, "end": 670},
{"lane": 2, "id": "North and South States", "start": 690, "end": 900},
{"lane": 2, "id": "Goryeo", "start": 920, "end": 1380},
{"lane": 2, "id": "Joseon", "start": 1390, "end": 1890},
{"lane": 2, "id": "Korean Empire", "start": 1900, "end": 1945}]
timeBegin = 0,
timeEnd = 2000;
</script>
<script type="text/javascript">
var m = [20, 15, 15, 120], //top right bottom left
w = 960 - m[1] - m[3],
h = 500 - m[0] - m[2],
miniHeight = laneLength * 12 + 50,
mainHeight = h - miniHeight - 50;
//scales
var x = d3.scale.linear()
.domain([timeBegin, timeEnd])
.range([0, w]);
var x1 = d3.scale.linear()
.range([0, w]);
var y1 = d3.scale.linear()
.domain([0, laneLength])
.range([0, mainHeight]);
var y2 = d3.scale.linear()
.domain([0, laneLength])
.range([0, miniHeight]);
var chart = d3.select("body")
.append("svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.attr("class", "chart");
chart.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", w)
.attr("height", mainHeight);
var main = chart.append("g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")")
.attr("width", w)
.attr("height", mainHeight)
.attr("class", "main");
var mini = chart.append("g")
.attr("transform", "translate(" + m[3] + "," + (mainHeight + m[0]) + ")")
.attr("width", w)
.attr("height", miniHeight)
.attr("class", "mini");
//main lanes and texts
main.append("g").selectAll(".laneLines")
.data(items)
.enter().append("line")
.attr("x1", m[1])
.attr("y1", function(d) {return y1(d.lane);})
.attr("x2", w)
.attr("y2", function(d) {return y1(d.lane);})
.attr("stroke", "lightgray")
main.append("g").selectAll(".laneText")
.data(lanes)
.enter().append("text")
.text(function(d) {return d;})
.attr("x", -m[1])
.attr("y", function(d, i) {return y1(i + .5);})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "laneText");
//mini lanes and texts
mini.append("g").selectAll(".laneLines")
.data(items)
.enter().append("line")
.attr("x1", m[1])
.attr("y1", function(d) {return y2(d.lane);})
.attr("x2", w)
.attr("y2", function(d) {return y2(d.lane);})
.attr("stroke", "lightgray");
mini.append("g").selectAll(".laneText")
.data(lanes)
.enter().append("text")
.text(function(d) {return d;})
.attr("x", -m[1])
.attr("y", function(d, i) {return y2(i + .5);})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "laneText");
var itemRects = main.append("g")
.attr("clip-path", "url(#clip)");
//mini item rects
mini.append("g").selectAll("miniItems")
.data(items)
.enter().append("rect")
.attr("class", function(d) {return "miniItem" + d.lane;})
.attr("x", function(d) {return x(d.start);})
.attr("y", function(d) {return y2(d.lane + .5) - 5;})
.attr("width", function(d) {return x(d.end - d.start);})
.attr("height", 10);
//mini labels
mini.append("g").selectAll(".miniLabels")
.data(items)
.enter().append("text")
.text(function(d) {return d.id;})
.attr("x", function(d) {return x(d.start);})
.attr("y", function(d) {return y2(d.lane + .5);})
.attr("dy", ".5ex");
//brush
var brush = d3.svg.brush()
.x(x)
.on("brush", display);
mini.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", 1)
.attr("height", miniHeight - 1);
display();
function display() {
var rects, labels,
minExtent = brush.extent()[0],
maxExtent = brush.extent()[1],
visItems = items.filter(function(d) {return d.start < maxExtent && d.end > minExtent;});
mini.select(".brush")
.call(brush.extent([minExtent, maxExtent]));
x1.domain([minExtent, maxExtent]);
//update main item rects
rects = itemRects.selectAll("rect")
.data(visItems, function(d) { return d.id; })
.attr("x", function(d) {return x1(d.start);})
.attr("width", function(d) {return x1(d.end) - x1(d.start);});
rects.enter().append("rect")
.attr("class", function(d) {return "miniItem" + d.lane;})
.attr("x", function(d) {return x1(d.start);})
.attr("y", function(d) {return y1(d.lane) + 10;})
.attr("width", function(d) {return x1(d.end) - x1(d.start);})
.attr("height", function(d) {return .8 * y1(1);});
rects.exit().remove();
//update the item labels
labels = itemRects.selectAll("text")
.data(visItems, function (d) { return d.id; })
.attr("x", function(d) {return x1(Math.max(d.start, minExtent) + 2);});
labels.enter().append("text")
.text(function(d) {return d.id;})
.attr("x", function(d) {return x1(Math.max(d.start, minExtent));})
.attr("y", function(d) {return y1(d.lane + .5);})
.attr("text-anchor", "start");
labels.exit().remove();
}
</script>
</body>
</html>
@randomblink

This comment has been minimized.

Copy link

@randomblink randomblink commented Sep 26, 2014

Commented code would REALLY help us newbs figure out what's going on in some of these amazing D3 codeblocks...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment