A burndown graph (commonly used in agile and scrum methodologies) created using the D3 charting framework.
A Pen by Chris Spittles on CodePen.
A burndown graph (commonly used in agile and scrum methodologies) created using the D3 charting framework.
A Pen by Chris Spittles on CodePen.
<div class="intro"> | |
<h1>D3 Burndown Chart</h1> | |
<p>A burndown graph (commonly used in agile and scrum methodologies) created using the D3 charting framework.</p> | |
</div> | |
<svg id="visualisation" width="1000" height="500" class="chart"></svg> |
$(function(){ | |
initChart(); | |
}); | |
function initChart() { | |
var lineDataActual = [{ | |
'x': 0, | |
'y': 200 | |
}, { | |
'x': 10, | |
'y': 50 | |
}, { | |
'x': 20, | |
'y': 180 | |
}, { | |
'x': 30, | |
'y': 60 | |
}, { | |
'x': 40, | |
'y': 120 | |
}, { | |
'x': 50, | |
'y': 30 | |
}]; | |
var svg = d3.select("#visualisation"), | |
width = 1000, | |
height = 500, | |
margins = { | |
top: 80, | |
right: 50, | |
bottom: 80, | |
left: 80 | |
}, | |
xMin = d3.min(lineDataActual, function (d) { | |
return d.x; | |
}), | |
xMax = d3.max(lineDataActual, function (d) { | |
return d.x; | |
}), | |
yMin = d3.min(lineDataActual, function (d) { | |
return d.y; | |
}), | |
yMax = d3.max(lineDataActual, function (d) { | |
return d.y; | |
}), | |
xRange = d3.scale.linear().range([margins.left, width - margins.right]).domain([ | |
xMin,xMax | |
]), | |
yRange = d3.scale.linear().range([height - margins.top, margins.bottom]).domain([ | |
yMin,yMax | |
]), | |
xAxis = d3.svg.axis() | |
.scale(xRange) | |
.tickSubdivide(true), | |
yAxis = d3.svg.axis() | |
.scale(yRange) | |
.orient("left") | |
.tickSubdivide(true); | |
function make_x_axis() { | |
return d3.svg.axis() | |
.scale(xRange) | |
.orient("bottom") | |
.tickSubdivide(true) | |
} | |
function make_y_axis() { | |
return d3.svg.axis() | |
.scale(yRange) | |
.orient("left") | |
.tickSubdivide(true) | |
} | |
svg.append("g") | |
.attr("class", "grid") | |
.attr("transform", "translate(0," + (height - margins.top) + ")") | |
.call(make_x_axis() | |
.tickSize((-height) + (margins.top + margins.bottom), 0, 0) | |
.tickFormat("") | |
) | |
svg.append("g") | |
.attr("class", "grid") | |
.attr("transform", "translate(" + (margins.left) + ",0)") | |
.call(make_y_axis() | |
.tickSize((-width) + (margins.right + margins.left), 0, 0) | |
.tickFormat("") | |
) | |
svg.append("svg:g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + (height - (margins.bottom)) + ")") | |
.call(xAxis); | |
svg.append("svg:g") | |
.attr("class", "y axis") | |
.attr("transform", "translate(" + (margins.left) + ",0)") | |
.call(yAxis); | |
var lineFunc = d3.svg.line() | |
.x(function (d) { | |
return xRange(d.x); | |
}) | |
.y(function (d) { | |
return yRange(d.y); | |
}) | |
.interpolate('basis'); | |
var lineDataIdeal = [{ | |
'x': xMin, | |
'y': yMax | |
}, { | |
'x': xMax, | |
'y': yMin | |
}]; | |
svg.append("svg:path") | |
.attr("d", lineFunc(lineDataIdeal)) | |
.attr("class", "ideal"); | |
svg.append("svg:path") | |
.attr("d", lineFunc(lineDataActual)) | |
.attr("class", "actual"); | |
svg.append("text") | |
.attr("class", "x label") | |
.attr("text-anchor", "end") | |
.attr("x", width) | |
.attr("y", height -6) | |
.text("Days"); | |
svg.append("text") | |
.attr("class", "y label") | |
.attr("text-anchor", "end") | |
.attr("y", 6) | |
.attr("dy", ".75em") | |
.attr("transform", "rotate(-90)") | |
.text("Hours remaining"); | |
} |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js"></script> |
.chart { | |
font-family: 'Arial'; | |
font-size: 13px; | |
color: #000; | |
} | |
.chart > .axis path, | |
.chart > .axis line { | |
fill: none; | |
stroke: #eee; | |
stroke-width:2; | |
shape-rendering: crispEdges; | |
} | |
.chart > .axis .tick line { | |
fill: none; | |
stroke: #999; | |
stroke-width:2; | |
} | |
.chart > path.ideal { | |
stroke: #eee; | |
stroke-width:5; | |
stroke-linecap:round; | |
} | |
.chart > path.actual { | |
stroke: #91E500; | |
stroke-width:2; | |
stroke-linecap:round; | |
fill: none; | |
/*fill: rgba(0,0,0,0.1);*/ | |
} | |
.chart > .grid .tick { | |
stroke: #eee; | |
opacity: 0.5; | |
} | |
/* For aesthetics only */ | |
body { | |
margin: 40px; | |
font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif; | |
} | |
.intro h1 { | |
font: 200 1.7em Segoe UI, "Segoe UI Light", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif; | |
font-weight: 200; | |
color: #666; | |
} | |
.intro p { | |
max-width: 600px; | |
} |