Last active
August 29, 2015 14:07
-
-
Save bsmithgall/dabebf0c7e57b781a886 to your computer and use it in GitHub Desktop.
Small Multiples - MultiLine
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
.chart { | |
float: left; | |
padding-right: 5px; | |
padding-bottom: 5px; | |
padding-top: 0; | |
padding-left: 0; | |
} | |
svg { | |
font-size: 10px; | |
} | |
.background{ | |
fill: none; | |
} | |
.line { | |
fill: none; | |
stroke-width: 1.5px; | |
} | |
.axis line, .grid line { | |
stroke-width: .5px; | |
shape-rendering: crispEdges; | |
stroke: #fff; | |
opacity: 0.5; | |
pointer-events :none; | |
} | |
.axis path { | |
display: none; | |
} | |
.hidden { | |
display: none; | |
opacity: 0.0; | |
} | |
.one { | |
stroke: steelblue; | |
} | |
.two { | |
stroke: orange; | |
} | |
</style> | |
</head> | |
<body> | |
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script> | |
<script type="text/javascript"> | |
var generateData = function(n, d) { | |
/* | |
generate n random date/value series of d days | |
*/ | |
var currentDate = new Date(); | |
var output = []; | |
for (var i=0; i<n; i++) { | |
var innerSeries = []; | |
for (var j=0; j<d; j++) { | |
var pushDate = new Date(currentDate.setDate(currentDate.getDate() - (d - j))).setHours(0,0,0,0); | |
// push "series" data | |
innerSeries.push({ | |
group: 'one', | |
x: pushDate, | |
y: Math.floor(Math.random() * 100) | |
}); | |
// push "control" data | |
innerSeries.push({ | |
group: 'two', | |
x: pushDate, | |
y: 40 | |
}); | |
currentDate = new Date(); | |
} | |
output.push({ | |
key: 'Group ' + i, | |
values: innerSeries | |
}); | |
} | |
return output; | |
}; | |
var data = generateData(10, 60) | |
function smallMultiples() { | |
var width = 360, | |
height = 90, | |
margin = {top: 15, right: 10, bottom: 40, left: 35}, | |
data =[]; | |
var circle = null, | |
caption = null, | |
curDate = null; | |
var bisect = d3.bisector(function(d) { | |
return d.x; }).left | |
var x = d3.time.scale().range([0, width]); | |
var y = d3.scale.linear().range([height, 0]); | |
var line = d3.svg.line() | |
.x(function(d) { return x(d.x); }) | |
.y(function(d) { return y(d.y); }) | |
var scales = function(data) { | |
var extentX, maxY; | |
maxY = d3.max(data, function(d) { | |
return d3.max(d.values, function(e) { | |
return e.y; | |
}); | |
}); | |
y.domain([0, maxY]); | |
extentX = d3.extent(data[0].values, function(d) { return d.x; }) | |
return x.domain(extentX); | |
} | |
function chart(selection) { | |
return selection.each(function(data, i) { | |
var div, g, lines, svg; | |
scales(data); | |
div = d3.select(this).selectAll('.chart') | |
.data(data); | |
div.enter().append('div') | |
.attr('class', 'chart') | |
.append('svg') | |
.append('g'); | |
svg = div.select('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
g = svg.select('g') | |
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); | |
// append rect to catch mouse events | |
g.append("rect").attr("class", "background") | |
.style("pointer-events", "all") | |
.attr("width", width + margin.right) | |
.attr("height", height) | |
.on("mouseover", mouseover) | |
.on("mousemove", mousemove) | |
.on("mouseout", mouseout) | |
g.each(multiple); | |
function multiple(symbol, i) { | |
var groups = d3.nest() | |
.key(function(d) { return d.group; }) | |
.entries(symbol.values) | |
g[0].forEach(function(elem, ix) { | |
if (i === ix) { | |
// draw lines inside our g element | |
lines = d3.select(elem).selectAll('.lines') | |
.data(groups) | |
.enter().append('g'); | |
lines.append('path') | |
.attr('class', function(d) { return 'line ' + d.key }) | |
.style('pointer-events', 'none') | |
.attr('d', function(d) { | |
return line(d.values); | |
}); | |
// draw circles | |
lines.append('circle') | |
.attr('r', 2.2) | |
.attr('opacity', 0) | |
.style('pointer-events', 'none') | |
} | |
}) | |
circle = g.selectAll('circle') | |
} | |
}); | |
}; | |
var mouseover = function() { | |
circle.attr('opacity', 1); | |
d3.selectAll('.static-year').classed('hidden', true); | |
return mousemove.call(this); | |
} | |
var mousemove = function() { | |
var date, index; | |
date = x.invert(d3.mouse(this)[0]).setHours(0,0,0,0); | |
index = 0; | |
circle | |
.attr('cx', x(date)) | |
.attr('cy', function(d) { | |
index = bisect(d.values, date, 0, d.values.length - 1); | |
return y(d.values[index].y); | |
}); | |
} | |
var mouseout = function() { | |
d3.selectAll('.static-year').classed('hidden', false); | |
circle.attr('opacity', 0); | |
} | |
return chart; | |
} | |
var plot = smallMultiples(); | |
d3.select('body').data([data]).call(plot); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment