forked from misanuk's block: Example of Small Multiples with Mouseover Tooltip
xxxxxxxxxx
<meta charset="utf-8">
<style type="text/css">
body {
font: 10px avenir next, sans-serif;
}
.request-line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.dimension-title {
font: bold 14px avenir next;
}
.dimension-box {
display: inline-block;
}
.x-axis {
stroke-width: 0.5px;
stroke: #888;
font: 12px avenir next, sans-serif;
}
.x-axis > path {
stroke: #888;
}
.y-axis {
stroke-width: 0.5px;
stroke: #888;
font: 12px avenir next, sans-serif;
}
.y-axis > path {
stroke: #888;
}
.overlay {
fill: none;
pointer-events: all;
}
.focus circle {
fill: none;
stroke: steelblue;
}
</style>
<body>
</body>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// Margin Conventions and Setup
var margin = {top: 0, right: 20, bottom: 15, left: 35};
var width = 250 - margin.left - margin.right;
var height = 200 - margin.top - margin.bottom;
// Format Functions
var parseTime = d3.timeParse("%Y-%m-%d");
var bisectDate = d3.bisector(function(d) { return d.month; }).left
// Line Defaults
var xScale = d3.scaleTime()
.range([0, width]);
var yScale = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(2)
.tickSize(0);
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(2)
.tickSize(0);
var line = d3.line()
.x(function(d) { return xScale(d.month); })
.y(function(d) { return yScale(d.requests); });
d3.csv("category_monthly.csv", function(error, data) {
if(error) throw error;
// Prep Data
data.forEach(function(d) {
d.month = parseTime(d.month);
d.requests = +d.requests;
})
//Update Scales
xScale.domain(d3.extent(data, function(d) { return d.month; }));
yScale.domain(d3.extent(data, function(d) { return d.requests; }));
// Nest Data
var dataByDimension = d3.nest()
.key(function(d) { return d.category; })
.entries(data);
// Join Data and create plots
var dimension = d3.select("body").selectAll(".dimension-group")
.data(dataByDimension)
.enter()
.append("div")
.attr("class", "dimension-box")
dimension.append("h3")
.attr("class", "dimension-title")
.text(function(d) { return d.key.slice(0,25); });
var svg = dimension.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis")
.call(yAxis);
svg.append("path")
.attr("class", "request-line")
.attr("d", function(d) { return line(d.values); });
// Mouseover Tooltip, based on Mike's example here: https://bl.ocks.org/mbostock/3902569
svg.each(function(){
var svg = d3.select(this),
category = svg.datum().key;
var filtered_data = svg.datum().values;
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 3);
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em");
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectDate(filtered_data, x0, 1),
d0 = filtered_data[i - 1],
d1 = filtered_data[i],
d = x0 - d0.month > d1.month - x0 ? d1 : d1;
focus.attr("transform", "translate(" + xScale(d.month) + "," + yScale(d.requests) + ")");
focus.select("text").text(d.requests);
};
})
});
</script>
https://d3js.org/d3.v4.js