JSFiddle - React, Tailwind, and code Playground
by Cezar Pendarovski
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.2/d3.min.js"></script>
CSS
svg {
border: thin solid lightgray;
}
rect.project {
opacity: 0.7;
stroke: black;
stroke-opacity: 0.5;
}
rect.frontend {
fill: orange;
}
rect.operations {
fill: blueviolet;
}
rect.devops {
fill: bisque;
}
rect.backend {
fill: salmon;
}
rect.database {
fill: green;
}
rect.marketing {
fill: cornsilk;
}
JavaScript
const projects = [
{
'name': 'foo',
'team': 'operations',
'start_date': '2018-01-01',
'end_date': '2019-12-31'
},
{
'name': 'bar',
'team': 'operations',
'start_date': '2017-01-01',
'end_date': '2018-12-31'
},
{
'name': 'abc',
'team': 'operations',
'start_date': '2018-01-01',
'end_date': '2018-08-31'
},
{
'name': 'xyz',
'team': 'devops',
'start_date': '2018-04-01',
'end_date': '2020-12-31'
},
{
'name': 'wtf',
'team': 'devops',
'start_date': '2018-01-01',
'end_date': '2019-09-30'
},
{
'name': 'qwerty',
'team': 'frontend',
'start_date': '2017-01-01',
'end_date': '2019-01-31'
},
{
'name': 'azerty',
'team': 'marketing',
'start_date': '2016-01-01',
'end_date': '2019-08-31'
},
{
'name': 'qwertz',
'team': 'backend',
'start_date': '2018-05-01',
'end_date': '2019-12-31'
},
{
'name': 'mysql',
'team': 'database',
'start_date': '2015-01-01',
'end_date': '2017-09-15'
},
{
'name': 'postgresql',
'team': 'database',
'start_date': '2016-01-01',
'end_date': '2018-12-31'
}
]
// Process data
projects.sort((a,b) => d3.ascending(a.start_date, b.start_date));
const data = d3.nest()
.key(d => d.team)
.entries(projects);
const flatData = d3.merge(data.map(d => d.values));
// Configure dimensions
const
barHeight = 16,
margin ={
top: 50,
left: 100,
right: 20,
bottom: 50
},
chart = {
width: 1000,
height: projects.length * barHeight
},
viewport = {
width: chart.width + margin.left + margin.right,
height: chart.height + margin.top + margin.bottom
},
tickBleed = 5,
labelPadding = 10
;
// Configure scales and axes
const xMin = d3.min(
flatData,
d => d3.isoParse(d.start_date)
);
const xMax = d3.max(
flatData,
d => d3.isoParse(d.end_date)
);
const xScale = d3.scaleTime()
.range([0, chart.width])
.domain([xMin, xMax])
;
const xAxis =...