Skip to content

Instantly share code, notes, and snippets.

@imjayson
Last active October 30, 2017 10:20
Show Gist options
  • Save imjayson/3cad8758b7242744e9862bfec61b4305 to your computer and use it in GitHub Desktop.
Save imjayson/3cad8758b7242744e9862bfec61b4305 to your computer and use it in GitHub Desktop.
Gantt Chart
license: MIT
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gantt Chart</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</head>
<body></body>
<script type="text/javascript" src="main.js"></script>
</html>
var parseDate = d3.time.format("%d-%b-%y").parse;
var data=[
{"step": "responseStart", "from": "1-Jan-17", "to": "15-Jan-17", "progress":100},
{"step": "Task 1", "from": "13-Jan-17", "to": "1-Feb-17", "progress":60},
{"step": "Task 1", "from": "1-Feb-17", "to": "15-Feb-17", "progress":70},
{"step": "Task 1", "from": "10-Feb-17", "to": "1-Mar-17", "progress":10},
{"step": "Task 1", "from": "1-Mar-17", "to": "12-Mar-17", "progress":90}
]
var types_of_statuses = ["Completed","Remaining"];
var statuses_color = ["#2ecc71","#e74c3c"];
data.forEach(function(d) {
d.from = parseDate(d.from);
d.to = parseDate(d.to);
});
var margin = {top: 50, right: 50, bottom: 50, left: 100},
width = 900 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], .2);
var x = d3.time.scale().range([0, width]);
y.domain(data.map(function(d) { return 'd.category'; }));
x.domain([d3.min(data,function(d){return d.from;}), d3.max(data,function(d){return d.to;})]);
var xAxis = d3.svg.axis().tickValues([]);
// .scale(x)
// .orient("bottom")
// .ticks(15)
// .tickFormat(d3.time.format("%d%b"));
var yAxis = d3.svg.axis().tickValues([]);
// .scale(y)
// .orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// svg.append("g")
// .attr("class", "x axis")
// .attr("transform", "translate(0," + height + ")")
// .call(xAxis)
// .append("text")
// .attr("x", width-margin.right)
// .attr("dx", ".71em")
// .attr("dy", "-0.2em")
// .text("Date");
// svg.append("g")
// .attr("class", "y axis")
// .call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y('d.category'); })
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.from); })
.attr("width", function(d) { return x(d.to) - x(d.from)});
svg.selectAll(".pending")
.data(data)
.enter().append("rect")
.attr("class", "pending")
.attr("y", function(d) { return y('d.category'); })
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.from) + (x(d.to) - x(d.from))*d.progress/100 })
.attr("width", function(d) { return (x(d.to) - x(d.from))*(1-(d.progress/100))});
// add legend
var legend = svg.append("g")
.attr("class", "legend")
legend.selectAll(".swatch")
.data(types_of_statuses)
.enter()
.append("rect")
.attr("x", width-margin.left-margin.right-25)
.attr("y", function(d, i){ return -margin.top/2 + i*20;})
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d,i) {
return statuses_color[i];
})
legend.selectAll(".labels")
.data(types_of_statuses)
.enter()
.append("text")
.attr("x", width-margin.left-margin.right)
.attr("y", function(d, i){ return -margin.top/2 + i*20 + 10;})
.text(function(d,i){return types_of_statuses[i]});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div').attr('class', 'category');
tooltip.append('div').attr('class', 'tempRange');
tooltip.append('div').attr('class', 'progress');
svg.selectAll(".bar,.pending")
.on('mouseover', function(d) {
tooltip.select('.category').html("<b>" + d.step + "</b>");
tooltip.select('.tempRange').html(d.from.toDateString() + " to " + d.to.toDateString());
tooltip.select('.progress').html(d.progress + "% completed");
tooltip.style('display', 'block');
tooltip.style('opacity',2);
})
.on('mousemove', function(d) {
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity',0);
});
.pending {
fill: #e74c3c;
}
.bar {
fill: #2ecc71;
}
.bar:hover, .pending:hover {
fill: #3498db;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font: 16px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment