Skip to content

Instantly share code, notes, and snippets.

@javi-aire
Last active August 29, 2015 14:26
Show Gist options
  • Select an option

  • Save javi-aire/e1482a4f013f91e54340 to your computer and use it in GitHub Desktop.

Select an option

Save javi-aire/e1482a4f013f91e54340 to your computer and use it in GitHub Desktop.
//ideas:
//arrows for dependencies
//percent complete fill up bar
//who is on the task?
//maybe manually set color argument?
//helper (end user) functions for adding and adjusting tasks
//
var w = 800;
var h = 400;
var svg = d3.selectAll(".svg")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("class", "svg")
var dateFormat = d3.time.format("%Y-%m-%d");
var timeScale = d3.time.scale()
.domain([[d3.min(taskArray, function(d) { return dateFormat.parse(d.startTime);}),
d3.max(taskArray, function(d) { return dateFormat.parse(d.endTime);})]])
.range([0, w-150]);
var categories = [];
for(var i = 0; i < taskArray.length; i++){
categories.push(taskArray[i].type);
}
var unfilteredCats = categories; //keeping a copy before we filter it (for use later)
categories = unique(categories);
//helper functions
//
//from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
function getCounts(arr) {
var i = arr.length; // var to loop over
var obj = {}; // obj to store results
while (i) obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
return obj;
}
// get specific from everything
function getCount(word, arr) {
return getCounts(arr)[word] || 0;
}
// taken from -- http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
function unique(arr) {
var hash = {}, result = [];
for ( var i = 0, l = arr.length; i < l; ++i ) {
if ( !hash.hasOwnProperty(arr[i]) ) { //it works with objects! in FF, at least
hash[ arr[i] ] = true;
result.push(arr[i]);
}
}
return result;
}
//end helper functions
//begin drawing functions
//
//Start declaring slave drawing functions
//
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h){
var bigRects = svg.append("g")
.selectAll("rect")
.data(theArray)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", function(d, i){
return i*theGap + theTopPad - 2;
})
}
function vertLabels(theGap, theTopPad, theSidePad, theBarHeight, theColorScale){
var numOccurences = [];
var prevGap = 0;
for(var i = 0; i < categories.length; i++){
numOccurences[i] = [categories[i], getCount(categories[i], unfilteredCats)];
}
var axisText = svg.append("g") //without this, it's impossible to put grid lines behind text
.selectAll("text")
.data(numOccurences)
.enter()
.append("text")
.text(function(d) {
return d[0];
})
.attr("x", 10)
.attr("y", function(d, i) {
if(i > 0){
for(var j = 0; j < i; j++){
prevGap += numOccurences[i-1][1];
return d[1]*theGap/2 + prevGap*theGap + theTopPad;
}
} else {
return d[1]*theGap/2 + theTopPad;
}
})
.attr("font-size", 11)
.attr("text-anchor", "start")
.attr("text-height", 14)
.attr("fill", function(d){
for(var i = 0; i < categories.length; i++){
if(d[0] === categories[i]){
return d3.rgb(theColorScale(i)).darker();
}
}
});
}
function makeGrid(theSidePad, theTopPad, w, h){
var xAxis = d3.svg.axis()
.scale(timeScale)
.orient('bottom')
.ticks(d3.time.days, 1)
.tickSize(-h+theTopPad+20, 0 ,0)
.tickFormat(d3.time.format('%d %b'));
var grid = svg.append('g')
.attr('class', 'grid')
.attr('transform', 'translate(' + theSidePad + ', ' + (h - 50) + ')')
.call(xAxis)
.selectAll("text") //X-Axis labels
.style("text-anchor", "middle")
.attr("fill", "#000")
.attr("stroke", "none")
.attr("font-size", 10)
.attr("dy", "1em");
}
//
//Build all the things (master function that calls slave functions)
//
function makeGantt(tasks, svgWidth, svgHeight){
var barHeight = 20;
var gap = barHeight + 5;
var topPadding = 75;
var sidePadding = 100;
var colorScale = d3.scale.linear()
.domain([0, categories.length])
.range("#2e8b57", "#0379A3")
.interpolate(d3.interpolateHcl);
makeGrid(sidePadding, topPadding, svgWidth, svgHeight);
drawRects(tasks, gap, topPadding, sidePadding, barHeight, colorScale, svgWidth, svgHeight);
vertLabels(gap, topPadding, sidePadding, barHeight, colorScale);
}
//call the master drawing function
makeGantt(taskArray, w, h);
//set interative rules
//rectText on mouseover
//innerRects on mouseover
//http://codepen.io/anon/pen/RPdamv
//http://codepen.io/anon/pen/RPdamv?editors=011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment