Last active
August 29, 2015 14:26
-
-
Save javi-aire/e1482a4f013f91e54340 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| //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