Skip to content

Instantly share code, notes, and snippets.

@nnattawat
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nnattawat/9720082 to your computer and use it in GitHub Desktop.
Save nnattawat/9720082 to your computer and use it in GitHub Desktop.
A reusable punchcard of yearly data

A reusable d3 punchcard inspired by Reuseable Charts article. Part of code is reused from mbostock's punchcard. Color and size of circles are varied based on their data point's value. I also add an option to use the same radius scale across all data sets.

The example can be view on bl.ocks.org.

/*
* Define chart
*/
function punchcard(){
// Default settings
var $el = d3.select("body");
var maxRadius = 9;
var minRadius = 2;
var margin = {top: 40, right: 200, bottom: 40, left: 20};
var width = 300;
var height = 200;
var color = "steelblue";
var data = [];
var object = {};
var formatTick = d3.format("0000");
var svg, x, xAxis, allValues, xScale, colorScale;
var rowHeight = (maxRadius*2)+2;
var useGlobalScale = true;
object.render = function(){
x = d3.scale.linear()
.range([0, width]);
xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
xAxis.ticks(data[0].values.length)
.tickFormat(formatTick);
svg = $el.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.bottom)
.style("margin-left", margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var domain = d3.extent(allValues, function(d){return d['key'];});
var valDomain = d3.extent(allValues, function(d){return d['value'];});
x.domain(domain);
xScale = d3.scale.linear()
.domain(domain)
.range([0, width]);
colorScale = d3.scale.linear()
.domain(d3.extent(allValues, function(d){return d['value'];}))
.range([d3.rgb(color).brighter(), d3.rgb(color).darker()]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(xAxis);
function mouseover(p) {
var g = d3.select(this).node().parentNode;
d3.select(g).selectAll("circle").style("display","none");
d3.select(g).selectAll("text.value").style("display","block");
}
function mouseout(p) {
var g = d3.select(this).node().parentNode;
d3.select(g).selectAll("circle").style("display","block");
d3.select(g).selectAll("text.value").style("display","none");
}
for (var j = 0; j < data.length; j++) {
var g = svg.append("g");
var circles = g.selectAll("circle")
.data(data[j]['values'])
.enter()
.append("circle");
var text = g.selectAll("text")
.data(data[j]['values'])
.enter()
.append("text");
var rDomain = useGlobalScale? valDomain : [0, d3.max(data[j]['values'], function(d) { return d['value']; })];
var rScale = d3.scale.linear()
.domain(rDomain)
.range([minRadius, maxRadius]);
circles
.attr("cx", function(d, i) { return xScale(d['key']); })
.attr("cy", (height - margin.bottom - rowHeight*2) - (j*rowHeight)+rowHeight)
.attr("r", function(d) { return rScale(d['value']); })
.style("fill", function(d) { return colorScale(d['value']) });
text
.attr("y",(height - margin.bottom - rowHeight*2) - (j*rowHeight)+(rowHeight+5))
.attr("x",function(d, i) { return xScale(d['key'])-5; })
.attr("class","value")
.text(function(d){ return d['value']; })
.style("fill", function(d) { return colorScale(d['value']) })
.style("display","none");
g.append("text")
.attr("y", (height - margin.bottom - rowHeight*2) - (j*rowHeight)+(rowHeight+5))
.attr("x",width+rowHeight)
.attr("class","label")
.text(data[j]['key'])
.style("fill", function(d) { return color })
.on("mouseover", mouseover)
.on("mouseout", mouseout);
};
return object;
};
// Getter and setter methods
object.data = function(value){
if (!arguments.length) return data;
data = value;
allValues = [];
data.forEach(function(d){
allValues = allValues.concat(d.values);
});
return object;
};
object.minRadius = function(value){
if (!arguments.length) return minRadius;
minRadius = value;
return object;
};
object.maxRadius = function(value){
if (!arguments.length) return maxRadius;
maxRadius = value;
rowHeight = (maxRadius*2)+2;
return object;
};
object.$el = function(value){
if (!arguments.length) return $el;
$el = value;
return object;
};
object.width = function(value){
if (!arguments.length) return width;
width = value;
return object;
};
object.height = function(value){
if (!arguments.length) return height;
height = value;
return object;
};
object.color = function(value){
if (!arguments.length) return color;
color = value;
return object;
};
object.useGlobalScale = function(value){
if (!arguments.length) return useGlobalScale;
useGlobalScale = value;
return object;
};
return object;
};
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
<!-- <script src="../d3.v3.js"></script> -->
<script src="d3.punchcard.js"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
}
.axis path,.axis line {
fill: none;
stroke: #b6b6b6;
shape-rendering: crispEdges;
}
.tick text{
fill: #999;
}
g.journal.active{
cursor:pointer;
}
text.label{
font-size:12px;font-weight:bold;cursor:pointer;
}
text.value{
font-size:12px;font-weight:bold;
}
</style>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript">
// Define mocked data
var data = [
{
key: "data-1",
values: [
{key: "2004", value: 8},
{key: "2005", value: 4},
{key: "2006", value: 10},
{key: "2007", value: 11},
{key: "2008", value: 6},
{key: "2009", value: 10},
{key: "2010", value: 16}
]
},
{
key: "data-2",
values: [
{key: "2004", value: 2},
{key: "2005", value: 4},
{key: "2006", value: 10},
{key: "2007", value: 7},
{key: "2008", value: 20},
{key: "2009", value: 6},
{key: "2010", value: 18}
]
},
{
key: "data-3",
values: [
{key: "2004", value: 1},
{key: "2005", value: 2},
{key: "2006", value: 3},
{key: "2007", value: 4},
{key: "2008", value: 6},
{key: "2009", value: 10},
{key: "2010", value: 4}
]
},
{
key: "data-4",
values: [
{key: "2004", value: 1},
{key: "2005", value: 2},
{key: "2006", value: 3},
{key: "2007", value: 4},
{key: "2008", value: 6},
{key: "2009", value: 10},
{key: "2010", value: 4}
]
}
];
// Create Punchcard
var punchcard = punchcard()
.$el(d3.select("#chart"))
.data(data)
.render();
// Uncomment this part to try out additional options
// var punchcard = punchcard()
// .$el(d3.select("#chart"))
// .data(data)
// .width(250)
// .height(300)
// .color("green")
// .minRadius(5)
// .useGlobalScale(false)
// .maxRadius(19)
// .render();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment