|
function Heatmap() { |
|
var margin = { |
|
top: 20, right: 100, bottom: 20, left: 50 |
|
}; |
|
|
|
var formatDate = d3.timeFormat("%m/%d @ %H"), |
|
tickFormat = d3.format(".1s") |
|
|
|
var x = d3.scaleTime(), |
|
y = d3.scaleLinear(), |
|
z = d3.scaleLinear(); |
|
|
|
var xValue = function(d) { return d.date; }, |
|
binAccessor = function(d) { return d.bucket; }, |
|
yValue = function(d) { return d.count; }; |
|
|
|
var xAxis = d3.axisBottom(x).tickFormat(formatDate); |
|
var yAxis = d3.axisLeft(y).tickFormat(tickFormat); |
|
var width, height, svg, chart; |
|
|
|
// The size of the buckets in the CSV data file. |
|
// This could be inferred from the data if it weren't sparse. |
|
var dayMs = 864e5, |
|
xStep = dayMs/24; |
|
|
|
function drawChart(data) { |
|
|
|
var el = d3.select(this).node(); |
|
width = el.clientWidth - margin.left - margin.right; |
|
height = el.clientHeight - margin.top - margin.bottom; |
|
|
|
// Compute the scale domains. |
|
x.domain(d3.extent(data, xValue)); |
|
y.domain(d3.extent(data, binAccessor)) |
|
z.domain(d3.extent(data, yValue)); |
|
|
|
// Extend the x-domain to fit the last bucket. |
|
x.domain([x.domain()[0], +x.domain()[1] + xStep]); |
|
|
|
x.range([0, width]) |
|
y.range([height, 0]) |
|
z.range(["white", "steelblue"]) |
|
|
|
xAxis.tickSize(-height) |
|
yAxis.tickSize(-width) |
|
|
|
svg = d3.select(this) |
|
.append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + (3*margin.bottom)) |
|
.append("g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
// Display the tiles for each non-zero bucket. |
|
chart = svg.selectAll(".tile") |
|
.data(data) |
|
.enter().append("rect") |
|
.attr("class", "tile") |
|
.attr("x", _.flow(xValue, x)) |
|
.attr("y", _.flow(binAccessor, y)) |
|
.attr("width", x(xStep) - x(0)) |
|
.attr("height", y(0) - y(100)) |
|
.style("fill", _.flow(yValue, z)) |
|
; |
|
|
|
// Add a legend for the color values. |
|
var legend = svg.selectAll(".legend") |
|
.data(z.ticks(6).slice(1).reverse()) |
|
.enter().append("g") |
|
.attr("class", "legend") |
|
.attr("transform", function(d, i) { |
|
return "translate(" + (width + 20) + "," + (20 + i * 20) + ")"; |
|
}); |
|
|
|
legend.append("rect") |
|
.attr("width", 20) |
|
.attr("height", 20) |
|
.style("fill", z); |
|
|
|
legend.append("text") |
|
.attr("x", 26) |
|
.attr("y", 10) |
|
.attr("dy", ".35em") |
|
.text(tickFormat); |
|
|
|
svg.append("text") |
|
.attr("class", "label") |
|
.attr("x", width + 20) |
|
.attr("y", 10) |
|
.attr("dy", ".35em") |
|
.text("Count"); |
|
|
|
// Add an x-axis with label. |
|
svg.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(xAxis) |
|
.append("text") |
|
.attr("class", "label") |
|
.attr("x", width) |
|
.attr("y", -6) |
|
.attr("text-anchor", "end") |
|
.text("Date"); |
|
|
|
// Add a y-axis with label. |
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.call(yAxis) |
|
.append("text") |
|
.attr("class", "label") |
|
.attr("y", 6) |
|
.attr("dy", ".71em") |
|
.attr("text-anchor", "end") |
|
.attr("transform", "rotate(-90)") |
|
.text("Milliseconds") |
|
; |
|
|
|
} |
|
|
|
function chart(selection) { |
|
selection.each(drawChart); |
|
} |
|
|
|
chart.chart = function (_) { |
|
if (!arguments.length) return chart; |
|
chart = _; |
|
return chart; |
|
} |
|
chart.svg = function (_) { |
|
if (!arguments.length) return svg; |
|
svg = _; |
|
return svg; |
|
}; |
|
|
|
chart.margin = function(_) { |
|
if (!arguments.length) return margin; |
|
margin = _; |
|
return chart; |
|
}; |
|
|
|
chart.width = function(_) { |
|
if (!arguments.length) return width; |
|
width = _; |
|
return chart; |
|
}; |
|
|
|
chart.height = function(_) { |
|
if (!arguments.length) return height; |
|
height = _; |
|
return chart; |
|
}; |
|
|
|
chart.x = function(_) { |
|
if (!arguments.length) return xValue; |
|
xValue = _; |
|
return chart; |
|
}; |
|
|
|
chart.y = function(_) { |
|
if (!arguments.length) return yValue; |
|
yValue = _; |
|
return chart; |
|
}; |
|
|
|
chart.xScale = function (_) { |
|
if (!arguments.length) return x; |
|
x = _; |
|
return chart; |
|
}; |
|
|
|
chart.yScale = function (_) { |
|
if (!arguments.length) return y; |
|
y = _; |
|
return chart; |
|
}; |
|
|
|
chart.xAxis = function (_) { |
|
if (!arguments.length) return xAxis; |
|
xAxis = _; |
|
return chart; |
|
}; |
|
|
|
chart.yAxis = function (_) { |
|
if (!arguments.length) return yAxis; |
|
yAxis = _; |
|
return chart; |
|
}; |
|
|
|
return chart; |
|
} |