Skip to content

Instantly share code, notes, and snippets.

@baramuyu
Last active April 12, 2022 03:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 31 You must be signed in to fork a gist
  • Save baramuyu/ad1f10371a305db47ebaf9779202f7ac to your computer and use it in GitHub Desktop.
Save baramuyu/ad1f10371a305db47ebaf9779202f7ac to your computer and use it in GitHub Desktop.
D3.js v4 Gantt Chart, example 3
license: mit
html,body,#wrapper {
width: 100%;
height: 100%;
margin: 0px;
}
.chart {
font-family: Arial, sans-serif;
font-size: 12px;
}
.axis path,.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: #33b5e5;
}
.bar-failed {
fill: #CC0000;
}
.bar-running {
fill: #669900;
}
.bar-succeeded {
fill: #33b5e5;
}
.bar-killed {
fill: #ffbb33;
}
#forkme_banner {
display: block;
position: absolute;
top: 0;
right: 5px;
z-index: 10;
padding: 10px 40px 10px 5px;
color: #fff;
background:
url('http://dk8996.github.io/Gantt-Chart/images/blacktocat.png')
#0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
text-decoration: none;
}
#twittme_banner {
display: block;
position: absolute;
top: 0;
right: 180px;
z-index: 10;
padding: 10px 40px 10px 5px;
color: #fff;
background:
url('http://dk8996.github.io/Gantt-Chart/images/twitter.png')
#0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
text-decoration: none;
}
var tasks = [
{"startDate":new Date("Sun Dec 09 00:00:45 EST 2012"),"endDate":new Date("Sun Dec 09 02:36:45 EST 2012"),"taskName":"E Job","status":"RUNNING"},
{"startDate":new Date("Sun Dec 09 08:49:53 EST 2012"),"endDate":new Date("Sun Dec 09 06:34:04 EST 2012"),"taskName":"D Job","status":"RUNNING"},
{"startDate":new Date("Sun Dec 09 03:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 03:58:43 EST 2012"),"taskName":"P Job","status":"SUCCEEDED"},
{"startDate":new Date("Sun Dec 09 03:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 03:58:43 EST 2012"),"taskName":"N Job","status":"KILLED"}
];
// var svg2 = d3.select("body").append("svg")
// .attr("width", 960)
// .attr("height", 100)
// svg2.append("text")
// .text(d3.timeDay.offset(getEndDate(), -7))
// .attr("y", 50)
var taskStatus = {
"SUCCEEDED" : "bar",
"FAILED" : "bar-failed",
"RUNNING" : "bar-running",
"KILLED" : "bar-killed"
};
var taskNames = [ "D Job", "P Job", "E Job", "A Job", "N Job" ];
tasks.sort(function(a, b) {
return a.endDate - b.endDate;
});
var maxDate = tasks[tasks.length - 1].endDate;
tasks.sort(function(a, b) {
return a.startDate - b.startDate;
});
var minDate = tasks[0].startDate;
var format = "%H:%M";
var timeDomainString = "1day";
var gantt = d3.gantt().height(450).width(800).taskTypes(taskNames).taskStatus(taskStatus).tickFormat(format);
// gantt.timeDomainMode("fixed");
changeTimeDomain(timeDomainString);
gantt(tasks);
function changeTimeDomain(timeDomainString) {
this.timeDomainString = timeDomainString;
switch (timeDomainString) {
case "1hr":
format = "%H:%M:%S";
gantt.timeDomain([ d3.timeHour.offset(getEndDate(), -1), getEndDate() ]);
break;
case "3hr":
format = "%H:%M";
gantt.timeDomain([ d3.timeHour.offset(getEndDate(), -3), getEndDate() ]);
break;
case "6hr":
format = "%H:%M";
gantt.timeDomain([ d3.timeHour.offset(getEndDate(), -6), getEndDate() ]);
break;
case "1day":
format = "%H:%M";
gantt.timeDomain([ d3.timeDay.offset(getEndDate(), -1), getEndDate() ]);
break;
case "1week":
format = "%a %H:%M";
gantt.timeDomain([ d3.timeDay.offset(getEndDate(), -7), getEndDate() ]);
break;
default:
format = "%H:%M"
}
gantt.tickFormat(format);
gantt.redraw(tasks);
}
function getEndDate() {
var lastEndDate = Date.now();
if (tasks.length > 0) {
lastEndDate = tasks[tasks.length - 1].endDate;
}
return lastEndDate;
}
function addTask() {
var lastEndDate = getEndDate();
var taskStatusKeys = Object.keys(taskStatus);
var taskStatusName = taskStatusKeys[Math.floor(Math.random() * taskStatusKeys.length)];
var taskName = taskNames[Math.floor(Math.random() * taskNames.length)];
tasks.push({
"startDate" : d3.timeHour.offset(lastEndDate, Math.ceil(1 * Math.random())),
"endDate" : d3.timeHour.offset(lastEndDate, (Math.ceil(Math.random() * 3)) + 1),
"taskName" : taskName,
"status" : taskStatusName
});
changeTimeDomain(timeDomainString);
gantt.redraw(tasks);
};
function removeTask() {
tasks.pop();
changeTimeDomain(timeDomainString);
gantt.redraw(tasks);
};
/**
* @author Dimitry Kudrayvtsev
* @version 2.0
*
* Ported to d3 v4 by Keyvan Fatehi on October 16th, 2016
*/
d3.gantt = function() {
var FIT_TIME_DOMAIN_MODE = "fit";
var FIXED_TIME_DOMAIN_MODE = "fixed";
var margin = {
top : 20,
right : 40,
bottom : 20,
left : 150
};
var timeDomainStart = d3.timeDay.offset(new Date(),-3);
var timeDomainEnd = d3.timeHour.offset(new Date(),+3);
var timeDomainMode = FIXED_TIME_DOMAIN_MODE;// fixed or fit
var taskTypes = [];
var taskStatus = [];
var height = document.body.clientHeight - margin.top - margin.bottom-5;
var width = document.body.clientWidth - margin.right - margin.left-5;
var tickFormat = "%H:%M";
var keyFunction = function(d) {
return d.startDate + d.taskName + d.endDate;
};
var rectTransform = function(d) {
return "translate(" + x(d.startDate) + "," + y(d.taskName) + ")";
};
var x,y,xAxis,yAxis;
initAxis();
var initTimeDomain = function() {
if (timeDomainMode === FIT_TIME_DOMAIN_MODE) {
if (tasks === undefined || tasks.length < 1) {
timeDomainStart = d3.timeDay.offset(new Date(), -3);
timeDomainEnd = d3.timeHour.offset(new Date(), +3);
return;
}
tasks.sort(function(a, b) {
return a.endDate - b.endDate;
});
timeDomainEnd = tasks[tasks.length - 1].endDate;
tasks.sort(function(a, b) {
return a.startDate - b.startDate;
});
timeDomainStart = tasks[0].startDate;
}
};
function initAxis() {
x = d3.scaleTime().domain([ timeDomainStart, timeDomainEnd ]).range([ 0, width ]).clamp(true);
y = d3.scaleBand().domain(taskTypes).range([ 0, height - margin.top - margin.bottom ]).padding(0.1);
xAxis = d3.axisBottom().scale(x).tickFormat(d3.timeFormat(tickFormat))
.tickSize(8).tickPadding(8);
yAxis = d3.axisLeft().scale(y).tickSize(0);
};
function gantt(tasks) {
initTimeDomain();
initAxis();
var svg = d3.select("body")
.append("svg")
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "gantt-chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
svg.selectAll(".chart")
.data(tasks, keyFunction).enter()
.append("rect")
.attr("rx", 5)
.attr("ry", 5)
.attr("class", function(d){
if(taskStatus[d.status] == null){ return "bar";}
return taskStatus[d.status];
})
.attr("y", 0)
.attr("transform", rectTransform)
.attr("height", function(d) { return 70; })
.attr("width", function(d) {
return (x(d.endDate) - x(d.startDate));
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + (height - margin.top - margin.bottom) + ")")
.transition()
.call(xAxis);
svg.append("g").attr("class", "y axis").transition().call(yAxis);
return gantt;
};
gantt.redraw = function(tasks) {
initTimeDomain();
initAxis();
var svg = d3.select("svg");
var ganttChartGroup = svg.select(".gantt-chart");
var rect = ganttChartGroup.selectAll("rect").data(tasks, keyFunction);
rect.enter()
.insert("rect",":first-child")
.attr("rx", 5)
.attr("ry", 5)
.attr("class", function(d){
if(taskStatus[d.status] == null){ return "bar";}
return taskStatus[d.status];
})
.transition()
.attr("y", 0)
.attr("transform", rectTransform)
.attr("height", function(d) { return y.bandwidth(); })
.attr("width", function(d) {
return (x(d.endDate) - x(d.startDate));
});
rect.merge(rect).transition()
.attr("transform", rectTransform)
.attr("height", function(d) { return y.bandwidth(); })
.attr("width", function(d) {
return (x(d.endDate) - x(d.startDate));
});
rect.exit().remove();
svg.select(".x").transition().call(xAxis);
svg.select(".y").transition().call(yAxis);
return gantt;
};
gantt.margin = function(value) {
if (!arguments.length)
return margin;
margin = value;
return gantt;
};
gantt.timeDomain = function(value) {
if (!arguments.length)
return [ timeDomainStart, timeDomainEnd ];
timeDomainStart = +value[0], timeDomainEnd = +value[1];
return gantt;
};
/**
* @param {string}
* vale The value can be "fit" - the domain fits the data or
* "fixed" - fixed domain.
*/
gantt.timeDomainMode = function(value) {
if (!arguments.length)
return timeDomainMode;
timeDomainMode = value;
return gantt;
};
gantt.taskTypes = function(value) {
if (!arguments.length)
return taskTypes;
taskTypes = value;
return gantt;
};
gantt.taskStatus = function(value) {
if (!arguments.length)
return taskStatus;
taskStatus = value;
return gantt;
};
gantt.width = function(value) {
if (!arguments.length)
return width;
width = +value;
return gantt;
};
gantt.height = function(value) {
if (!arguments.length)
return height;
height = +value;
return gantt;
};
gantt.tickFormat = function(value) {
if (!arguments.length)
return tickFormat;
tickFormat = value;
return gantt;
};
return gantt;
};
<!DOCTYPE html>
<html>
<head>
<title>Gantt Chart Example 3</title>
<link type="text/css" href="http://mbostock.github.io/d3/style.css" rel="stylesheet" />
<link type="text/css" href="example.css" rel="stylesheet" />
</head>
<body>
<button type="button" onclick="addTask()">Add Task</button>
<button type="button" onclick="removeTask()">Remove Task</button>
<button type="button" onclick="changeTimeDomain('1hr')">1 HR</button>
<button type="button" onclick="changeTimeDomain('3hr')">3 HR</button>
<button type="button" onclick="changeTimeDomain('6hr')">6 HR</button>
<button type="button" onclick="changeTimeDomain('1day')">1 DAY</button>
<button type="button" onclick="changeTimeDomain('1week')">1 WEEK</button>
</body>
</html>
<script type="text/javascript" src="http://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script type="text/javascript" src="http://d3js.org/d3-time-format.min.js"></script>
<script type="text/javascript" src="gantt.js"></script>
<script type="text/javascript" src="example3.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment