|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Composable Visualization Test</title> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> |
|
<style> |
|
body { |
|
margin: 0; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<script> |
|
var width = 960; |
|
var height = 500; |
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var data = [ |
|
{ name: "A"}, |
|
{ name: "B"}, |
|
{ name: "C"} |
|
]; |
|
|
|
var rect = Rect() |
|
.colorBy("name") |
|
.color(d3.scale.category10()) |
|
|
|
var facetVertical = FacetVertical() |
|
.width(width) |
|
.height(height) |
|
.nestBy("name"); |
|
|
|
// Define the composition of facet and rect. |
|
facetVertical.compose(rect); |
|
|
|
svg.datum(data).call(facetVertical); |
|
|
|
// This component draws a single rectangle. |
|
function Rect(){ |
|
var color; |
|
var colorBy; |
|
|
|
function my(selection){ |
|
selection.each(function (data){ |
|
|
|
var rects = d3.select(this) |
|
.selectAll("rect") |
|
.data(data); |
|
|
|
rects.enter().append("rect"); |
|
|
|
rects |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
if(colorBy){ |
|
rects.attr("fill", function (d){ |
|
return color(d[colorBy]); |
|
}); |
|
} |
|
|
|
rects.exit().remove(); |
|
}); |
|
} |
|
|
|
my.width = function (value){ |
|
if(arguments.length === 0) return width; |
|
width = value; |
|
return my; |
|
}; |
|
my.height = function (value){ |
|
if(arguments.length === 0) return height; |
|
height = value; |
|
return my; |
|
}; |
|
my.color = function (value){ |
|
if(arguments.length === 0) return color; |
|
color = value; |
|
return my; |
|
}; |
|
my.colorBy = function (value){ |
|
if(arguments.length === 0) return colorBy; |
|
colorBy = value; |
|
return my; |
|
}; |
|
return my; |
|
} |
|
|
|
// This component facets space vertically, |
|
// and could be used to create small multiples. |
|
function FacetVertical(){ |
|
var width; |
|
var height; |
|
|
|
var compose; |
|
var nestBy; |
|
|
|
function my(selection){ |
|
selection.each(function (data){ |
|
|
|
var nested = d3.nest() |
|
.key(function (d){ return d[nestBy]; }) |
|
.entries(data) |
|
.map(function (d){ return d.values; }); |
|
|
|
var groups = d3.select(this) |
|
.selectAll("g") |
|
.data(nested) |
|
|
|
groups.enter().append("g"); |
|
groups.attr("transform", function (d, i){ |
|
var y = height * i / nested.length; |
|
return "translate(0," + y + ")"; |
|
}); |
|
|
|
groups.exit().remove(); |
|
|
|
compose.width(width); |
|
compose.height(height / nested.length); |
|
|
|
groups.call(compose); |
|
}); |
|
} |
|
|
|
my.width = function (value){ |
|
if(arguments.length === 0) return width; |
|
width = value; |
|
return my; |
|
}; |
|
my.height = function (value){ |
|
if(arguments.length === 0) return height; |
|
height = value; |
|
return my; |
|
}; |
|
my.compose = function (value){ |
|
if(arguments.length === 0) return compose; |
|
compose = value; |
|
return my; |
|
}; |
|
my.nestBy = function (value){ |
|
if(arguments.length === 0) return nestBy; |
|
nestBy = value; |
|
return my; |
|
}; |
|
return my; |
|
} |
|
|
|
</script> |
|
</body> |