Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
var allocation = function(d3, ctx) {
var colours = d3.scale.category10();
var dateFormat = d3.time.format("%b-%d-%Y");
var dateDomain = [
d3.min(ctx.projects, function(p) { return dateFormat.parse(p.start); }),
d3.max(ctx.projects, function(p) { return dateFormat.parse(p.end); })
];
var dateScale = d3.time.scale().domain(dateDomain).range([0, ctx.height - 24]);
var svg = d3.select('#chart').append('svg').
attr('width', ctx.width).
attr('height', ctx.height);
function pairs(array) {
var result = [];
for(var i = 0; i < array.length - 1; i++) {
result.push([array[i], array[i+1]]);
}
return result;
}
function projectLane(x) {
x += 1; // never return 0
return x % 2 === 0 ? Math.floor(-1 * x / 2) : Math.ceil(x / 2);
}
function extractConsultantMovements(c) {
var result = [];
pairs(c.allocations).forEach(function(pair) {
result.push({
name: c.name,
start: [projectCalled(pair[0].name).offset, scaledDate(pair[0].end)],
end: [projectCalled(pair[1].name).offset, scaledDate(pair[1].start)]
});
});
return result;
}
function extractConsultantAllocations(c) {
var result = [];
c.allocations.forEach(function(a) {
result.push({
name: c.name,
project: a.name,
start: a.start,
end: a.end
});
});
return result;
}
function scaledDate(dateAsString, defaultValue) {
var date = dateFormat.parse(dateAsString);
return (date ? dateScale(date) : defaultValue);
}
function projectCalled(name) {
return ctx.projects.filter(function(e) { return e.name == name; })[0];
}
var marginTop = 48,
marginLeft = 24;
function createAllocation(g) {
g.append('line').
attr('x1', function(d) { return projectCalled(d.project).offset;}).
attr('y1', function(d) { return scaledDate(d.start);}).
attr('x2', function(d) { return projectCalled(d.project).offset;}).
attr('y2', function(d) { return scaledDate(d.end, ctx.width);}).
attr('stroke', function(d) { return colours(d.name); }).
attr('transform', function() { return 'translate(' + marginTop + ',' + marginLeft + ')';});
}
function createMovement(g) {
g.append('line').
attr('x1', function(d) { return d.start[0]; }).
attr('y1', function(d) { return d.start[1]; }).
attr('x2', function(d) { return d.end[0]; }).
attr('y2', function(d) { return d.end[1]; }).
attr('stroke', function(d) { return colours(d.name); }).
attr('transform', function() { return 'translate(' + marginTop + ',' + marginLeft + ')';});
}
function createProject(g) {
var w = 96,
h = 24;
g.append('rect').
attr('x', 0).
attr('y', function(d) { return scaledDate(d.start); }).
attr('width', w).
attr('height', h).
attr('fill', 'black');
g.append('text').
text(function(d) { return d.name; }).
attr('x', h * 2).
attr('y', function(d) { return scaledDate(d.start) + (h / 2); }).
attr('text-anchor', 'middle').
attr('fill', 'white');
g.append('line').
attr('x1', h * 2).
attr('y1', function(d, i) { return scaledDate(d.start) + h; }).
attr('x2', h * 2).
attr('y2', function(d, i) { return scaledDate(d.end) + h; }).
attr('class', 'timeline');
g.append('line').
attr('x1', w / 3).
attr('y1', function(d) { return scaledDate(d.end) + h; }).
attr('x2', w - w / 3).
attr('y2', function(d) { return scaledDate(d.end) + h; }).
attr('stroke', 'black');
}
svg.selectAll('.project').
data(ctx.projects).
enter().
append('g').
attr('class', 'project').
attr('transform', function(d, i) { d.offset = ctx.distance * i ; return 'translate(' + d.offset + ',0)'; }).
call(createProject);
var consultants = svg.selectAll('.consultant').
data(ctx.consultants).
enter().
append('g').
attr('class', 'consultant').
attr('transform', function(d, i) { return 'translate(' + (projectLane(i)*2) + ')'; });
consultants.selectAll('.allocation').
data(extractConsultantAllocations).
enter().
append('g').
attr('class', 'allocation').
call(createAllocation);
consultants.selectAll('.movement').
data(extractConsultantMovements).
enter().
append('g').
attr('class', 'movement').
call(createMovement);
var yAxis = d3.svg.axis().
scale(dateScale).
tickSize(- ctx.width).
orient('right');
svg.append('g').
attr('class', 'axis').
attr('transform', 'translate(' + (ctx.width - 60) + ',' + 24 + ')').
call(yAxis);
};
<!DOCTYPE html>
<html>
<head>
<title>Allocation</title>
<script src="http://d3js.org/d3.v2.js"></script>
<link rel='stylesheet' type='text/css' href='styles.css'/>
<script src="allocation.js"></script>
</head>
<body>
<div id=chart></div>
<script>
d3.selectAll('#chart svg').remove();
var context = {
width: 400,
height: 500,
distance: 100,
projects : [
{ name: 'Project A', start: 'Jan-01-2012', end: 'Jun-31-2012'},
{ name: 'Project B', start: 'Jan-01-2012', end: 'Jun-31-2012'},
],
consultants : [
{ name: 'Alice', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Bob', allocations: [{ start: 'Jan-01-2012', end: 'Feb-28-2012', name: 'Project A'},{ start: 'Mar-01-2012', end: 'May-30-2012', name: 'Project B'}]},
{ name: 'Carl', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Dave', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Ed', allocations: [{ start: 'Jan-01-2012', end: 'Feb-20-2012', name: 'Project A'},{ start: 'Mar-01-2012', end: 'May-28-2012', name: 'Project B'}]},
{ name: 'Fred', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Gabe', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Harry', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Ian', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Joe', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Kate', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Luke', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Mike', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Neil', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Otto', allocations: [{ start: 'Jan-01-2012', end: 'Mar-15-2012', name: 'Project A'},{ start: 'Mar-18-2012', end: 'Jun-25-2012', name: 'Project B'}]},
{ name: 'Pam', allocations: [{ start: 'Jan-01-2012', end: 'Mar-15-2012', name: 'Project A'},{ start: 'Mar-18-2012', end: 'Jun-25-2012', name: 'Project B'}]},
{ name: 'Quinn', allocations: [{ start: 'Jan-01-2012', end: 'Mar-15-2012', name: 'Project A'},{ start: 'Mar-29-2012', end: 'Jun-25-2012', name: 'Project B'}]},
{ name: 'Russ', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Sam', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Tim', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Uli', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
{ name: 'Vince', allocations: [{ start: 'Jan-01-2012', end: 'Jun-25-2012', name: 'Project A'},]},
]
};
allocation(d3, context);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Allocation</title>
<script src="http://d3js.org/d3.v2.js"></script>
<link rel='stylesheet' type='text/css' href='styles.css'/>
<script src="allocation.js"></script>
</head>
<body>
<div id=chart></div>
<script>
d3.selectAll('#chart svg').remove();
var context = {
width: 800,
height: 1500,
distance: 96 - 40,
projects : [
{ name: 'Project A', start: 'Aug-08-2011', end: 'Aug-19-2011'},
{ name: 'Project B', start: 'Jan-17-2011', end: 'Aug-03-2011'},
{ name: 'Project C', start: 'Sep-05-2011', end: 'Nov-12-2012'},
{ name: 'Project D', start: 'Feb-01-2010', end: 'Dec-31-2012'},
{ name: 'Project E', start: 'Jul-05-2011', end: 'Jul-01-2013'},
{ name: 'Project F', start: 'Sep-01-2009', end: 'Nov-18-2009'},
{ name: 'Project G', start: 'Dec-14-2009', end: 'Aug-12-2011'},
{ name: 'Project H', start: 'Apr-11-2011', end: 'Dec-04-2012'},
{ name: 'Project I', start: 'Aug-22-2011', end: 'Oct-07-2012'},
{ name: 'Project J', start: 'Jan-17-2011', end: 'Dec-30-2011'},
{ name: 'Project K', start: 'Jun-27-2011', end: 'Jan-20-2012'},
{ name: 'Project L', start: 'Nov-28-2011', end: 'Jan-11-2013'}
],
consultants : [
{ name: 'Alice', allocations: [
{ start: 'Sep-01-2009', end: 'Nov-18-2009', name: 'Project F'},
{ start: 'Dec-14-2009', end: 'Aug-31-2010', name: 'Project G'},
{ start: 'Nov-15-2010', end: 'Dec-31-2010', name: 'Project D'},
{ start: 'Jan-17-2011', end: 'Feb-11-2011', name: 'Project B'},
{ start: 'Feb-14-2011', end: 'Apr-08-2011', name: 'Project B'},
{ start: 'Apr-11-2011', end: 'Apr-26-2011', name: 'Project H'},
{ start: 'May-09-2011', end: 'May-20-2011', name: 'Project H'},
{ start: 'May-23-2011', end: 'Aug-03-2011', name: 'Project B'},
{ start: 'Aug-08-2011', end: 'Aug-19-2011', name: 'Project A'},
{ start: 'Sep-05-2011', end: 'Sep-14-2011', name: 'Project C'},
{ start: 'Oct-10-2011', end: 'Nov-04-2011', name: 'Project H'},
{ start: 'Nov-09-2011', end: 'Jul-18-2012', name: 'Project H'},
{ start: 'Jul-18-2012', end: 'Aug-24-2012', name: 'Project C'},
{ start: 'Aug-23-2012', end: 'Jul-01-2013', name: 'Project E'}
]},
{ name: 'Bob', allocations: [
{ start: 'Dec-24-2009', end: 'Sep-30-2010', name: 'Project G'},
{ start: 'Oct-11-2010', end: 'May-27-2011', name: 'Project G'},
{ start: 'Jun-06-2011', end: 'Jul-15-2011', name: 'Project G'},
{ start: 'Aug-22-2011', end: 'Oct-07-2011', name: 'Project I'},
{ start: 'Oct-10-2011', end: 'Dec-23-2011', name: 'Project J'},
{ start: 'Dec-26-2011', end: 'Dec-04-2012', name: 'Project H'}
]},
{ name: 'Carl', allocations: [
{ start: 'Feb-01-2011', end: 'Aug-04-2011', name: 'Project D'},
{ start: 'Aug-08-2011', end: 'Dec-20-2011', name: 'Project K'},
{ start: 'Dec-21-2011', end: 'Apr-02-2012', name: 'Project H'},
{ start: 'Apr-16-2012', end: 'Jan-11-2013', name: 'Project L'}
]},
{ name: 'Ed', allocations: [
{ start: 'Oct-25-2010', end: 'Jan-21-2011', name: 'Project G'},
{ start: 'Jan-24-2011', end: 'Feb-11-2011', name: 'Project B'},
{ start: 'Feb-14-2011', end: 'Apr-08-2011', name: 'Project B'},
{ start: 'Apr-11-2011', end: 'Apr-26-2011', name: 'Project H'},
{ start: 'May-09-2011', end: 'May-20-2011', name: 'Project H'},
{ start: 'Aug-08-2011', end: 'Aug-19-2011', name: 'Project A'},
{ start: 'Sep-05-2011', end: 'Oct-07-2011', name: 'Project H'},
{ start: 'Oct-10-2011', end: 'Nov-04-2011', name: 'Project H'},
{ start: 'Nov-09-2011', end: 'Dec-06-2011', name: 'Project H'},
{ start: 'Dec-07-2011', end: 'Apr-20-2012', name: 'Project H'}
]}
]
};
allocation(d3, context);
</script>
</body>
</html>
text {
font-family: sans-serif;
text-anchor: middle;
dominant-baseline: central;
}
.consultant line {
stroke-width: 3;
stroke-linejoin: round;
stroke-opacity: 0.5;
}
.project {
opacity: 0.3;
}
.timeline {
stroke: black;
stroke-width: 1;
shape-rendering: crispEdges;
}
.consultant text {
font-size: 8pt;
text-anchor: start;
}
.axis {
shape-rendering: crispEdges;
stroke: 'black';
stroke-width: 1;
}
.axis text {
font-size: 8pt;
text-anchor: start;
dominant-baseline: auto;
}
.axis line, .axis path {
fill: none;
}
.axis line.tick {
stroke: black;
stroke-opacity: 0.03;
stroke-width: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment