This as-simple-as-possible example tries to demonstrate Mike Bostock's pattern "Towards Reusable Charts" http://bost.ocks.org/mike/chart/ for d3 plugins that are composite shapes.
-
-
Save bjtucker/5cc43014c1a2ec6cb878 to your computer and use it in GitHub Desktop.
Simple example of reusable d3 plugin.
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> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"> | |
<title>really simple d3 plugin example</title> | |
</head> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
width: 960px; | |
height: 500px; | |
position: relative; | |
} | |
</style> | |
<body> | |
<div id="chart"> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script type="text/javascript" src="textblock.js"></script> | |
<script> | |
var items = [ | |
{x : 50, y : 50, label : 'interesting label'}, | |
{x : 100, y: 120, label : 'some arb example'}, | |
{x : 300, y: 100, label : 'the last block'} | |
]; | |
// we can increase this, everything will scale up with us | |
var w=960,h=500, | |
svg=d3.select("#chart") | |
.append("svg") | |
.attr("width",w) | |
.attr("height",h); | |
// calling textBlock() returns the function object textBlock().my | |
// via which we set the "label" property of the textBlock outer func | |
var tb = d3.textBlock().label(function(d) {return d.label;}); | |
// now we apply the returned function object my == tb on an enter selection | |
var item = svg.selectAll("rect") | |
.data(items) | |
.enter() | |
.append("svg:g") | |
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) | |
.call(tb); | |
</script> | |
</body> | |
</html> |
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
/** | |
* textBlock - a really simple demonstration of a reusable d3 element / | |
* plugin following Mike Bostock's "Towards Reusable Charts" pattern on | |
* http://bost.ocks.org/mike/chart/ | |
* | |
* This simply draws a rect around the text specified in the label property. | |
* | |
* This example is also available as a block: | |
* http://bl.ocks.org/cpbotha/5073718 | |
* | |
* Other more complex examples that folow this pattern are: | |
* https://github.com/d3/d3-plugins/tree/master/bullet | |
* https://github.com/d3/d3-plugins/tree/master/chernoff | |
* | |
* author: Charl P. Botha - http://charlbotha.com/ | |
*/ | |
d3.textBlock = function() { | |
// label property: this will get drawn enclosed perfectly by a rect | |
var label = ""; | |
// this function object is returned when textBlock() is invoked. | |
// after setting properties (label above), it can be invoked on | |
// a whole selection by using call() -- see the rest of the example. | |
function my(selection) { | |
selection.each(function(d, i) { | |
// inside here, d is the current data item, i is its index. | |
// "this" is the element that has been appended, in the case of | |
// this example, a svg:g | |
// the text property could have been specified by the user as a | |
// value, or a function of the current data item. | |
var labelvar = (typeof(label) === "function" ? label(d) : label); | |
// convert element (svg:g) into something that D3 can use | |
// element is a single-element selection | |
var element = d3.select(this); | |
// first append text to svg:g | |
var t = element.append("text") | |
.text(labelvar) // here we set the label property on the text element | |
.attr("dominant-baseline", "central"); // vertically centered | |
// get the bounding box of the just created text element | |
var bb = t[0][0].getBBox(); | |
// then append svg rect to svg:g | |
// doing some adjustments so we fit snugly around the text: we're | |
// inside a transform, so only have to move relative to 0 | |
element.append("rect") | |
.attr("x", -5) // 5px margin | |
.attr("y", - bb.height) // so text is vertically within block | |
.attr("width", bb.width + 10) // 5px margin on left + right | |
.attr("height", bb.height * 2) | |
.attr("fill", "steelblue") | |
.attr("fill-opacity", 0.3) | |
.attr("stroke", "black") | |
.attr("stroke-width", 2); | |
}); | |
} | |
// getter / setter for the label property | |
my.label = function(value) { | |
if (!arguments.length) return value; | |
label = value; | |
return my; | |
}; | |
return my; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment