diff --git a/force_labels/README.md b/force_labels/README.md
index 519605f..4ef4c16 100644
--- a/force_labels/README.md
+++ b/force_labels/README.md
@@ -1,8 +1,15 @@
-# D3 Force Labels v 0.1
+# D3 Force Labels
-Demo:
+Demo:
-Generates an automatic and dynamic positioning for labels, using the d3 force layout. Once a```force_labels``` object has been created, simply call the bound function ```update``` with a selection of the objects you want to attach labels to as an argument. The force_labels object is a d3.force object which allows full control over the charge, gravity, theta etc.
+Generates an automatic and dynamic positioning for labels, using the d3 force layout. Once a ```forceLabels``` object has been created, simply call the bound function ```update``` with a selection of the objects you want to attach labels to as an argument.
+
+`forceLabels()` returns a [`d3.forceSimulation()`](https://github.com/d3/d3-force/blob/master/README.md#forceSimulation) object which allows full control over the charge strength, etc.
+
+For example, to change the charge strength, you could do something like this:
+```
+labelSim.force('charge').strength(-60);
+```
At each tick the following occurs:
@@ -11,19 +18,30 @@ At each tick the following occurs:
Both the ```anchorPos``` and ```labelPos``` are inserted in the ```__data__``` variable of the object being labeled. This allows easy access when drawing the labels and connectors.
-In the demo the label and link are created as svg objects on the same data selection as the anchors. As the position information is embedded in ```__data__``` the redraw function is simply:
+In the demo the label and link are created as svg objects on the same data selection as the anchors. As the position information is embedded in ```__data__```, the redraw function is simply:
```js
function redrawLabels() {
- labelBox
- .attr("transform",function(d) { return "translate("+d.labelPos.x+" "+d.labelPos.y+")"});
-
- links
- .attr("x1",function(d) { return d.anchorPos.x})
- .attr("y1",function(d) { return d.anchorPos.y})
- .attr("x2",function(d) { return d.labelPos.x})
- .attr("y2",function(d) { return d.labelPos.y});
+ labelBox
+ .attr("transform", function(d) {
+ return "translate(" + d.labelPos.x + " " + d.labelPos.y + ")"
+ })
+
+ links
+ .attr("x1", function(d) { return d.anchorPos.x })
+ .attr("y1", function(d) { return d.anchorPos.y })
+ .attr("x2", function(d) { return d.labelPos.x })
+ .attr("y2", function(d) { return d.labelPos.y })
}
-```
+```
+
+which is attached like this:
+```js
+labelSim = d3.forceLabels()
+ .on("tick", redrawLabels)
+```
+
+## Authors
-
\ No newline at end of file
+-
+-
diff --git a/force_labels/force_labels.js b/force_labels/force_labels.js
index cfa4454..ba86a43 100644
--- a/force_labels/force_labels.js
+++ b/force_labels/force_labels.js
@@ -1,57 +1,64 @@
(function() {
- d3.force_labels = function force_labels() {
- var labels = d3.layout.force();
-
+ d3.forceLabels = function forceLabels() {
+ var labelSim = d3.forceSimulation()
+
// Update the position of the anchor based on the center of bounding box
function updateAnchor() {
- if (!labels.selection) return;
- labels.selection.each(function(d) {
+ if (!labelSim.selection) return;
+
+ labelSim.selection.each(function(d) {
var bbox = this.getBBox(),
- x = bbox.x + bbox.width / 2,
- y = bbox.y + bbox.height / 2;
+ x = bbox.x + bbox.width/2,
+ y = bbox.y + bbox.height/2
+
+ d.anchorPos.x = x
+ d.anchorPos.y = y
- d.anchorPos.x = x;
- d.anchorPos.y = y;
-
- // If a label position does not exist, set it to be the anchor position
+ // If a label position does not exist, set it to be the anchor position
if (d.labelPos.x == null) {
- d.labelPos.x = x;
- d.labelPos.y = y;
+ d.labelPos.x = x
+ d.labelPos.y = y
}
- });
+ })
}
-
- //The anchor position should be updated on each tick
- labels.on("tick.labels", updateAnchor);
-
+
+ // The anchor position should be updated on each tick
+ labelSim.on("tick.labels", updateAnchor)
+
// This updates all nodes/links - retaining any previous labelPos on updated nodes
- labels.update = function(selection) {
- labels.selection = selection;
+ labelSim.update = function(selection) {
+ labelSim.selection = selection
var nodes = [], links = [];
- selection[0].forEach(function(d) {
- if(d && d.__data__) {
- var data = d.__data__;
-
- if (!d.labelPos) d.labelPos = {fixed: false};
- if (!d.anchorPos) d.anchorPos = {fixed: true};
-
- // Place position objects in __data__ to make them available through
+ selection.nodes().forEach(function(d) {
+ if (d && d.__data__) {
+ var data = d.__data__
+
+ if (!d.labelPos) d.labelPos = {fixed:false}
+ if (!d.anchorPos) d.anchorPos = {fixed:true}
+
+ // Place position objects in __data__ to make them available through
// d.labelPos/d.anchorPos for different elements
- data.labelPos = d.labelPos;
- data.anchorPos = d.anchorPos;
-
- links.push({target: d.anchorPos, source: d.labelPos});
- nodes.push(d.anchorPos);
- nodes.push(d.labelPos);
+ data.labelPos = d.labelPos
+ data.anchorPos = d.anchorPos
+
+ links.push({target:d.anchorPos, source:d.labelPos})
+ nodes.push(d.anchorPos)
+ nodes.push(d.labelPos)
}
- });
- labels
- .stop()
- .nodes(nodes)
- .links(links);
- updateAnchor();
- labels.start();
- };
- return labels;
- };
-})();
+ })
+
+ // Initialize simulation with nodes and some default forces (can be
+ // changed later by user)
+ labelSim
+ .nodes(nodes)
+ .force("charge", d3.forceManyBody())
+ .force("link", d3.forceLink()
+ .links(links)
+ .id(function id(d) { return d.id; })
+ .distance(function id(link, i) { return 10; })
+ )
+ updateAnchor()
+ }
+ return labelSim
+ }
+})()