Skip to content

Commit

Permalink
Merge pull request #8 from curran/padding
Browse files Browse the repository at this point in the history
Padding
  • Loading branch information
curran committed Jul 29, 2017
2 parents 33fa8d1 + 11356c4 commit 5394751
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 15 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ If you use NPM, `npm install d3-area-label`. Otherwise, download the [latest rel

<a href="#area-label" name="area-label">#</a> <b>areaLabel</b>(<i>area</i>)

Computes the optimal position and size for a label. Also positions the label using SVG transform.
Returns a function that computes the optimal position and size for a label and returns a transform string.

Example usage:

Expand All @@ -24,7 +24,7 @@ labels
.attr('class', 'area-label')
.merge(labels)
.text(d => d.key)
.each(d3.areaLabel(area)) // <--------------------- Call the function like this.
.attr('transform', d3.areaLabel(area)) // <---------- Call the function like this.
```

For more details and context, see [test/index.html](test/index.html).
Expand Down
66 changes: 54 additions & 12 deletions src/area-label.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Finds the largest value that passes the test within some epsilon tolerance.
// See https://en.wikipedia.org/wiki/Bisection_method#Algorithm
function bisection(a, b, test, epsilon, maxIterations) {
var i, c, passesTest, withinEpsilon;
Expand Down Expand Up @@ -38,8 +39,12 @@ function areaLabel(area) {

// The maximum number of iterations for the bisection method.
// Typical iterations for convervence on 0.001 epsilon are between 15 and 20.
maxIterations = 100;
maxIterations = 100,

paddingLeft = 0,
paddingRight = 0,
paddingTop = 0,
paddingBottom = 0;

// Returns true if there is at least one rectangle
// of the given aspect ratio and scale
Expand Down Expand Up @@ -94,7 +99,8 @@ function areaLabel(area) {
// Output the coordinates for use in label transform.
return {
x: x0,
y: ceiling
y: ceiling,
width: width
};
}
}
Expand All @@ -104,10 +110,16 @@ function areaLabel(area) {
function my(data) {

// The bounding box of the text label as-is.
var bbox = this.getBBox();
var box = this.getBBox();

// Account for padding.
var paddingFactorX = 1 + paddingLeft + paddingRight;
var paddingFactorY = 1 + paddingTop + paddingBottom;
var boxWidth = box.width * paddingFactorX;
var boxHeight = box.height * paddingFactorY;

// The aspect ratio of the text label bounding box.
var aspect = bbox.width / bbox.height;
var aspect = boxWidth / boxHeight;

// The test function for use in the bisection method.
var test = function (testHeight){
Expand All @@ -116,19 +128,21 @@ function areaLabel(area) {

// Use the bisection method to find the largest height label that fits.
var height = bisection(minHeight, maxHeight, test, epsilon, maxIterations);
var width = aspect * height;

// Get the X and Y coordinates for the largest height label that fits.
var fit = fits(data, aspect, height);
var x = fit.x;
var y = fit.y;

// Account for padding.
var fitX = fit.x + width / paddingFactorX * paddingLeft;
var fitY = fit.y + height / paddingFactorY * paddingTop;

// Translate and scale the label to the computed position and size.
d3.select(this)
.attr("transform", [
"translate(" + x + "," + y + ")",
"scale(" + height / bbox.height + ")",
"translate(" + -bbox.x + "," + -bbox.y + ")"
].join(" "));
return [
"translate(" + fitX + "," + fitY + ")",
"scale(" + height / boxHeight + ")",
"translate(" + -box.x + "," + -box.y + ")"
].join(" ");
}

my.x = function(_) {
Expand Down Expand Up @@ -169,6 +183,34 @@ function areaLabel(area) {
return arguments.length ? (maxIterations = +_, my) : maxIterations;
};

my.paddingLeft = function(_) {
return arguments.length ? (paddingLeft = +_, my) : paddingLeft;
};

my.paddingRight = function(_) {
return arguments.length ? (paddingRight = +_, my) : paddingRight;
};

my.paddingTop = function(_) {
return arguments.length ? (paddingTop = +_, my) : paddingTop;
};

my.paddingBottom = function(_) {
return arguments.length ? (paddingBottom = +_, my) : paddingBottom;
};

my.paddingX = function(_) {
my.paddingLeft(_).paddingRight(_);
};

my.paddingY = function(_) {
my.paddingTop(_).paddingBottom(_);
};

my.padding = function(_) {
my.paddingX(_).paddingY(_);
};

if (area) {
my.area(area);
}
Expand Down
2 changes: 1 addition & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
.attr('class', 'area-label')
.merge(labels)
.text(d => d.key)
.each(d3.areaLabel(area))
.attr('transform', d3.areaLabel(area))

</script>
</body>
Expand Down

0 comments on commit 5394751

Please sign in to comment.