An example of d3.layout.timeline that shows wars the United States has been involved in during its first 100 years (from Wikipedia). Events have been categorized and rendered in separate lanes for colonial wars, native wars, internal wars, wars involving European powers, and wars in Latin America.
Last active
June 19, 2023 20:42
-
-
Save emeeks/3184af35f4937d878ac0 to your computer and use it in GitHub Desktop.
d3.layout.timeline categorized timelines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
d3.layout.timeline = function() { | |
var timelines = []; | |
var dateAccessor = function (d) {return new Date(d)}; | |
var processedTimelines = []; | |
var startAccessor = function (d) {return d.start}; | |
var endAccessor = function (d) {return d.end}; | |
var size = [500,100]; | |
var timelineExtent = [-Infinity, Infinity]; | |
var setExtent = []; | |
var displayScale = d3.scale.linear(); | |
var swimlanes = []; | |
var padding = 0; | |
var fixedExtent = false; | |
var maximumHeight = Infinity; | |
function processTimelines() { | |
timelines.forEach(function (band) { | |
var projectedBand = {}; | |
for (var x in band) { | |
if (band.hasOwnProperty(x)) { | |
projectedBand[x] = band[x]; | |
} | |
} | |
projectedBand.start = dateAccessor(startAccessor(band)); | |
projectedBand.end = dateAccessor(endAccessor(band)); | |
projectedBand.lane = 0; | |
processedTimelines.push(projectedBand); | |
}); | |
} | |
function projectTimelines() { | |
if (fixedExtent === false) { | |
var minStart = d3.min(processedTimelines, function (d) {return d.start}); | |
var maxEnd = d3.max(processedTimelines, function (d) {return d.end}); | |
timelineExtent = [minStart,maxEnd]; | |
} | |
else { | |
timelineExtent = [dateAccessor(setExtent[0]), dateAccessor(setExtent[1])]; | |
} | |
displayScale.domain(timelineExtent).range([0,size[0]]); | |
processedTimelines.forEach(function (band) { | |
band.originalStart = band.start; | |
band.originalEnd = band.end; | |
band.start = displayScale(band.start); | |
band.end = displayScale(band.end); | |
}); | |
} | |
function fitsIn(lane, band) { | |
if (lane.end < band.start || lane.start > band.end) { | |
return true; | |
} | |
var filteredLane = lane.filter(function (d) {return d.start <= band.end && d.end >= band.start}); | |
if (filteredLane.length === 0) { | |
return true; | |
} | |
return false; | |
} | |
function findlane(band) { | |
//make the first array | |
if (swimlanes[0] === undefined) { | |
swimlanes[0] = [band]; | |
return; | |
} | |
var l = swimlanes.length - 1; | |
var x = 0; | |
while (x <= l) { | |
if (fitsIn(swimlanes[x], band)) { | |
swimlanes[x].push(band); | |
return; | |
} | |
x++; | |
} | |
swimlanes[x] = [band]; | |
return; | |
} | |
function timeline(data) { | |
if (!arguments.length) return timeline; | |
timelines = data; | |
processedTimelines = []; | |
swimlanes = []; | |
processTimelines(); | |
projectTimelines(); | |
processedTimelines.forEach(function (band) { | |
findlane(band); | |
}); | |
var height = size[1] / swimlanes.length; | |
height = Math.min(height, maximumHeight); | |
swimlanes.forEach(function (lane, i) { | |
lane.forEach(function (band) { | |
band.y = i * (height); | |
band.dy = height - padding; | |
band.lane = i; | |
}); | |
}); | |
return processedTimelines; | |
} | |
timeline.dateFormat = function (_x) { | |
if (!arguments.length) return dateAccessor; | |
dateAccessor = _x; | |
return timeline; | |
} | |
timeline.bandStart = function (_x) { | |
if (!arguments.length) return startAccessor; | |
startAccessor = _x; | |
return timeline; | |
} | |
timeline.bandEnd = function (_x) { | |
if (!arguments.length) return endAccessor; | |
endAccessor = _x; | |
return timeline; | |
} | |
timeline.size = function (_x) { | |
if (!arguments.length) return size; | |
size = _x; | |
return timeline; | |
} | |
timeline.padding = function (_x) { | |
if (!arguments.length) return padding; | |
padding = _x; | |
return timeline; | |
} | |
timeline.extent = function (_x) { | |
if (!arguments.length) return timelineExtent; | |
fixedExtent = true; | |
setExtent = _x; | |
if (_x.length === 0) { | |
fixedExtent = false; | |
} | |
return timeline; | |
} | |
timeline.maxBandHeight = function (_x) { | |
if (!arguments.length) return maximumHeight; | |
maximumHeight = _x; | |
return timeline; | |
} | |
return timeline; | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<title>Categorized Timeline Using Dates</title> | |
<meta charset="utf-8" /> | |
<style type="text/css"> | |
svg { | |
height: 1100px; | |
width: 1100px; | |
} | |
div.viz { | |
height: 1000px; | |
width: 1000px; | |
} | |
</style> | |
</head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js" charset="utf-8" type="text/javascript"></script> | |
<script src="d3.layout.timeline.js" charset="utf-8" type="text/javascript"></script> | |
<script> | |
types = ["European","Native","Colonial","Latin America","Internal"]; | |
colorScale = d3.scale.ordinal() | |
.domain(types) | |
.range(["#96abb1", "#313746", "#b0909d", "#687a97", "#292014"]); | |
d3.csv("wars.csv", function (csv) { | |
var timeline = d3.layout.timeline() | |
.size([500,80]) | |
.extent(["7/4/1776", "12/31/1876"]) | |
.padding(3) | |
.maxBandHeight(20); | |
types.forEach(function (type, i) { | |
onlyThisType = csv.filter(function(d) {return d.sphere === type}); | |
theseBands = timeline(onlyThisType); | |
d3.select("svg").append("g") | |
.attr("transform", "translate(100," + (35 + (i * 90)) + ")") | |
.selectAll("rect") | |
.data(theseBands) | |
.enter() | |
.append("rect") | |
.attr("rx", 2) | |
.attr("x", function (d) {return d.start}) | |
.attr("y", function (d) {return d.y}) | |
.attr("height", function (d) {return d.dy}) | |
.attr("width", function (d) {return d.end - d.start}) | |
.style("fill", function (d) {return colorScale(d.sphere)}) | |
.style("stroke", "black") | |
.style("stroke-width", 1); | |
d3.select("svg").append("text") | |
.text(type) | |
.attr("y", 50 + (i * 90)) | |
.attr("x", 20) | |
}) | |
}) | |
</script> | |
<body> | |
<div id="viz"> | |
<svg style="background:white;" height=1100 width=1100> | |
</svg> | |
</div> | |
<footer> | |
</footer> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name | start | end | sphere | |
---|---|---|---|---|
American Revolutionary War | 4/19/1775 | 9/3/1783 | European | |
Cherokee–American wars | 01/01/1776 | 12/31/1795 | Native | |
Northwest Indian War | 01/01/1785 | 12/31/1795 | Native | |
Whiskey Rebellion | 01/01/1795 | 12/31/1795 | Internal | |
Quasi-War | 01/01/1798 | 12/31/1800 | European | |
First Barbary War | 5/10/1801 | 6/10/1805 | Colonial | |
Tecumseh's War | 01/01/1811 | 12/31/1811 | Native | |
War of 1812 | 6/18/1812 | 2/18/1815 | European | |
Red Stick War | 01/01/1813 | 8/31/1814 | Native | |
Second Barbary War | 06/17/1815 | 06/19/1815 | Colonial | |
First Seminole War | 01/01/1817 | 12/31/1818 | Native | |
Texas/Indian Wars | 01/01/1820 | 12/31/1875 | Native | |
Arikara War | 01/01/1823 | 12/31/1823 | Native | |
Aegean Sea Anti/Piracy Operations | 01/01/1825 | 12/31/1828 | Colonial | |
Winnebago War | 01/01/1827 | 12/31/1827 | Native | |
First Sumatran expedition | 01/01/1832 | 12/31/1832 | Colonial | |
Black Hawk War | 01/01/1832 | 12/31/1832 | Native | |
Second Seminole War | 01/01/1835 | 12/31/1842 | Native | |
Patriot War | 01/01/1838 | 12/31/1838 | European | |
United States Exploring Expedition | 01/01/1838 | 12/31/1842 | Colonial | |
Second Sumatran expedition | 01/01/1838 | 12/31/1838 | Colonial | |
Mexican–American War | 01/01/1846 | 12/31/1848 | Latin America | |
Cayuse War | 01/01/1847 | 12/31/1855 | Native | |
Taiping Rebellion | 01/01/1850 | 12/31/1864 | Colonial | |
Apache Wars | 01/01/1851 | 12/31/1900 | Native | |
Bombardment of Greytown | 01/01/1854 | 12/31/1854 | European | |
Puget Sound War | 01/01/1855 | 12/31/1856 | Native | |
First Fiji Expedition | 01/01/1855 | 12/31/1855 | Colonial | |
Rogue River Wars | 01/01/1855 | 12/31/1856 | Native | |
Third Seminole War | 01/01/1855 | 12/31/1858 | Native | |
Yakima War | 01/01/1855 | 12/31/1858 | Native | |
Filibuster War | 01/01/1856 | 12/31/1857 | Latin America | |
Second Opium War | 01/01/1856 | 12/31/1859 | Colonial | |
Utah War | 01/01/1857 | 12/31/1858 | Internal | |
Navajo Wars | 01/01/1858 | 12/31/1866 | Native | |
Second Fiji Expedition | 01/01/1858 | 12/31/1858 | Colonial | |
First and Second Cortina War | 01/01/1859 | 12/31/1861 | Latin America | |
Paiute War | 01/01/1860 | 12/31/1860 | Native | |
Reform War | 01/01/1860 | 12/31/1860 | Latin America | |
American Civil War | 01/01/1861 | 12/31/1865 | Internal | |
Bombardment of Qui Nhơn | 01/01/1861 | 12/31/1861 | Colonial | |
Yavapai Wars | 01/01/1861 | 12/31/1875 | Native | |
Dakota War of 1862 | 01/01/1862 | 12/31/1862 | Native | |
Colorado War | 01/01/1863 | 12/31/1865 | Native | |
Shimonoseki War | 01/01/1863 | 12/31/1864 | Colonial | |
Snake War | 01/01/1864 | 12/31/1868 | Native | |
Powder River War | 01/01/1865 | 12/31/1865 | Native | |
Red Cloud's War | 01/01/1866 | 12/31/1868 | Native | |
Siege of Mexico City | 01/01/1867 | 12/31/1867 | Latin America | |
Formosa Expedition | 01/01/1867 | 12/31/1867 | Colonial | |
Comanche Campaign | 01/01/1867 | 12/31/1875 | Native | |
United States expedition to Korea | 01/01/1871 | 12/31/1871 | Colonial | |
Modoc War | 01/01/1872 | 12/31/1873 | Native | |
Red River War | 01/01/1874 | 12/31/1875 | Native | |
Las Cuevas War | 01/01/1875 | 12/31/1875 | Latin America | |
Great Sioux War of 1876 | 01/01/1876 | 12/31/1877 | Native | |
Buffalo Hunters' War | 01/01/1876 | 12/31/1877 | Native |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment