Some D3 Fiddlin
by Trever Shick
HTML
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.3.1/lodash.min.js"></script>
<script>
data = [{
"Client": "ABC",
"sale": "202",
"year": "2000"
}, {
"Client": "ABC",
"sale": "215",
"year": "2002"
}, {
"Client": "ABC",
"sale": "179",
"year": "2004"
}, {
"Client": "ABC",
"sale": "199",
"year": "2006"
}, {
"Client": "ABC",
"sale": "134",
"year": "2008"
}, {
"Client": "ABC",
"sale": "176",
"year": "2010"
}, {
"Client": "XYZ",
"sale": "100",
"year": "2000"
}, {
"Client": "XYZ",
"sale": "215",
"year": "2002"
}, {
"Client": "XYZ",
"sale": "179",
"year": "2004"
}, {
"Client": "XYZ",
"sale": "199",
"year": "2006"
}, {
"Client": "XYZ",
"sale": "134",
"year": "2008"
}, {
"Client": "XYZ",
"sale": "176",
"year": "2013"
}];
dataGroup = _.groupBy(data, "Client");
colors = ['red','orange','green','blue','purple'];
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<div class="container">
<div class="jumbotron well">
<div id="j" style="margin:0;padding:0">
</div>
</div>
</div>
CSS
#j {
height:80%;
}
.legend {
font-weight:bold;
}
.jumbotron {
padding:0;
height:400px;
}
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
JavaScript
var WIDTH = document.getElementById("j").offsetWidth;
var HEIGHT = 300;
var vis = d3.select("#j").append("svg")
.attr("width",WIDTH)
.attr("height",HEIGHT+50);
var MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
};
// build the legend
var lSpace = WIDTH/_.size(dataGroup);
function randomColor(){
return "hsl(" + Math.random() * 360 + ",100%,50%)"
}
function aggs(fns, data, onAttribute) {
return _.map(fns, function(fn) { return agg(fn, data, onAttribute); });
}
function agg(fn, data, onAttribute) {
return fn(data, function(d) { return d[onAttribute]; });
}
var xScale = d3.scale
.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain(aggs([d3.min, d3.max], data, 'year'));
var yScale = d3.scale
.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain(aggs([d3.min, d3.max], data, 'sale'));
var xAxis = d3.svg.axis()
.ticks(4)
.tickFormat(function(d){ return d; })
.scale(xScale);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
vis.append("svg:g")
.attr("class","axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")").call(xAxis);
vis.append("svg:g")
.attr("class","axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)").call(yAxis);
var lineGen = d3.svg.line()
.x(function(d) {
return xScale(d.year);
})
.y(function(d) {
return yScale(d.sale);
})
.interpolate("basis");
var i=0;
_.forEach(dataGroup, function(v,key) {
vis.append('svg:path')
.attr('d', lineGen(v))
.attr('stroke', colors.pop())
.attr('stroke-width', 2)
.attr('id', 'line_'+key)
.attr('fill', 'none');
vis.append("text")
.attr("class","legend")
.attr("x", (lSpace / 2) + (i++) * lSpace)
.attr("y", HEIGHT + 15)
.attr('id', 'leg_'+key)
.style("fill", "black")
.on('click', function() {
var active =...