Skip to content
Permalink
Browse files

feat: added xScale / yScale properties for easier integration with d3…

… cartesian chart
  • Loading branch information...
ColinEberhardt committed Oct 16, 2017
1 parent 391163d commit 97d1b2f82f39144701ba5a44f7e6f555062d80c5
Showing with 41 additions and 8 deletions.
  1. +12 −3 README.md
  2. +2 −0 package.json
  3. +26 −3 src/label.js
  4. +1 −2 test/bundleSpec.js
@@ -54,7 +54,9 @@ svg.datum(places.features)
.call(labels);
```

The above snippet is taken from block [389c76c6a544af9f0cab](http://bl.ocks.org/ColinEberhardt/389c76c6a544af9f0cab) which provides a complete example showing how this label layout component can be used to arrange labels on a map.
The above snippet is taken from a complete example showing how this [label layout component can be used to arrange labels on a map](http://bl.ocks.org/ColinEberhardt/389c76c6a544af9f0cab).

For integration with charts the label layout component exposes `xScale` and `yScale` properties, as [shown in this example](https://bl.ocks.org/ColinEberhardt/27508a7c0832d6e8132a9d1d8aaf231c/a49aac43f1bd770506dc3660aba149193f7def8b).

### Label

@@ -71,16 +73,23 @@ Each `g` element has the following properties set:

<a name="layoutLabel_size" href="#layoutLabel_size">#</a> *layoutLabel*.**size**(*accessor*)

Specifies the size for each item in the associated array. The *accessor* function is invoked exactly once per datum, and should return the size as an array of two values, `[width, height]`. The *accessor* function is invoked with the datum, and index. This function is invoked after the component has been rendered, and the value of the *this* context is the containing `g` element. As a result, you can measure the size of the component if the contents are dynamic, for example, measuring the size of a text label.
Specifies the size for each item in the associated array. The *accessor* function is invoked exactly once per datum, and should return the size as an array of two values, `[width, height]`. The *accessor* function is invoked with the current datum (d), the current index (i), and the current group (nodes). This function is invoked after the component has been rendered, and the value of the *this* context is the containing `g` element. As a result, you can measure the size of the component if the contents are dynamic, for example, measuring the size of a text label.

<a name="layoutLabel_position" href="#layoutLabel_position">#</a> *layoutLabel*.**position**(*accessor*)

Specifies the position for each item in the associated array. The *accessor* function is invoked exactly once per datum, and should return the position as an array of two values, `[x, y]`.
Specifies the position for each item in the associated array. The *accessor* function is invoked exactly once per datum, with the current datum (d), the current index (i), and the current group (nodes), and should return the position as an array of two values, `[x, y]`.

<a name="layoutLabel_component" href="#layoutLabel_component">#</a> *layoutLabel*.**component**(*component*)

Specified the component that is used to render each label.

<a name="layoutLabel_xScale" href="#layoutLabel_xScale">#</a> *layoutLabel*.**xScale**(*scale*)
<a name="layoutLabel_yScale" href="#layoutLabel_yScale">#</a> *layoutLabel*.**yScale**(*scale*)

If *scale* is specified, sets the scale and returns the label layout component. If *scale* is not specified, returns the current scale.

The scales are applied to the position of each item, i.e. `[x, y] -> [xScale(x), yScale(y)]`, with the default scale being an identity.

### Strategy

The label component uses a strategy in order to re-locate labels to avoid collisions, or perhaps hide those that overlap.
@@ -24,11 +24,13 @@
"deploy-site": "npm run site && bash ./site/deploy.sh"
},
"devDependencies": {
"d3": "^4.11.0",
"d3fc-scripts": "^1.1.4",
"watch-cli": "^0.2.1"
},
"dependencies": {
"d3-array": "^1.0.0",
"d3-scale": "^1.0.6",
"d3-selection": "^1.0.0",
"d3fc-data-join": "^2.0.0",
"d3fc-rebind": "^4.0.0"
@@ -1,5 +1,6 @@
import { sum } from 'd3-array';
import { select } from 'd3-selection';
import { scaleIdentity } from 'd3-scale';
import functor from './util/functor';
import { dataJoin as dataJoinUtil } from 'd3fc-data-join';
import { include, rebindAll } from 'd3fc-rebind';
@@ -11,6 +12,8 @@ export default (layoutStrategy) => {
let position = (d, i) => [d.x, d.y];
let strategy = layoutStrategy || ((x) => x);
let component = () => {};
let xScale = scaleIdentity();
let yScale = scaleIdentity();

const dataJoin = dataJoinUtil('g', 'label');

@@ -26,7 +29,11 @@ export default (layoutStrategy) => {
const childRects = nodes
.map((node, i) => {
let d = select(node).datum();
let childPos = position(d, i, nodes);
const pos = position(d, i, nodes);
let childPos = [
xScale(pos[0]),
yScale(pos[1])
];
let childSize = size(d, i, nodes);
return {
hidden: false,
@@ -46,8 +53,8 @@ export default (layoutStrategy) => {
// set the layout width / height so that children can use SVG layout if required
.attr('layout-width', (_, i) => layout[i].width)
.attr('layout-height', (_, i) => layout[i].height)
.attr('anchor-x', (d, i, g) => position(d, i, g)[0] - layout[i].x)
.attr('anchor-y', (d, i, g) => position(d, i, g)[1] - layout[i].y);
.attr('anchor-x', (d, i, g) => childRects[i].x - layout[i].x)
.attr('anchor-y', (d, i, g) => childRects[i].y - layout[i].y);

g.call(component);

@@ -90,5 +97,21 @@ export default (layoutStrategy) => {
return label;
};

label.xScale = (...args) => {
if (!args.length) {
return xScale;
}
xScale = args[0];
return label;
};

label.yScale = (...args) => {
if (!args.length) {
return yScale;
}
yScale = args[0];
return label;
};

return label;
};
@@ -7,8 +7,7 @@ describe('bundle', () => {
html: '<html></html>',
virtualConsole: jsdom.createVirtualConsole().sendTo(console),
scripts: [
'./node_modules/d3-array/build/d3-array.js',
'./node_modules/d3-selection/build/d3-selection.js',
'./node_modules/d3/build/d3.js',
'./node_modules/d3fc-data-join/build/d3fc-data-join.js',
'./node_modules/d3fc-rebind/build/d3fc-rebind.js',
'./build/d3fc-label-layout.js'

0 comments on commit 97d1b2f

Please sign in to comment.
You can’t perform that action at this time.