Skip to content
mbostock edited this page Jul 3, 2011 · 27 revisions

API ReferenceLayouts

Enclosure diagrams use containment (nesting) to represent the hierarchy. The size of each circle reveals a quantitative dimension of each data point, and the cumulative size of each subtree. Although circle packing does not use space as efficiently as a treemap, the “wasted” space more effectively reveals the hierarchy.

pack

By flattening the hierarchy, the pack layout can also be used to create bubble charts:

bubble

Like other classes in D3, layouts follow the method chaining pattern where setter methods return the layout itself, allowing multiple setters to be invoked in a concise statement.

# d3.layout.pack()

Creates a new pack layout with the default settings: the default sort order is by ascending value; the default children accessor assumes each input data is an object with a children array; the default size is 1×1.

# pack.sort([comparator])

If comparator is specified, sets the sort order of sibling nodes for the layout using the specified comparator function. If comparator is not specified, returns the current group sort order, which defaults to ascending order by the associated input data's numeric value attribute:

function comparator(a, b) {
  return a.value - b.value;
}

The comparator function is invoked for pairs of nodes, being passed the input data for each node. A null comparator disables sorting and uses tree traversal order. Comparator functions may also be implemented using d3.ascending or d3.descending.

# pack.children([children])

If children is specified, sets the specified children accessor function. If children is not specified, returns the current children accessor function, which by default assumes that the input data is an object with a children array:

function children(d) {
  return d.children;
}

The children accessor is first invoked for root node in the hierarchy. If the accessor returns null, then the node is assumed to be a leaf node at the layout traversal terminates. Otherwise, the accessor should return an array of data elements representing the child nodes.

Often, it is convenient to load the node hierarchy using d3.json, and represent the input hierarchy efficiently as a nested JSON object, rather than an explicit array of children. In this case, the leaf nodes of the hierarchy may be simple numbers rather than objects. Using the children accessor function, you can easily tell the layout how to traverse the input hierarchy. For example, if the input is:

{
  "analytics": {
    "cluster": {
      "AgglomerativeCluster": 3938,
      "CommunityStructure": 3812,
      "MergeEdge": 743
    },
    "graph": {
      "BetweennessCentrality": 3534,
      "LinkDistance": 5731
    }
  }
}

Then a suitable children accessor will iterate over the values in each object, if the current node is an object, or return null for non-objects to indicate that the specified input is a leaf node:

function children(d) {
  return isNaN(d) ? d3.values(d) : null;
}

However, note that with this accessor, the data associated with each node will only have access to the child nodes, and will not know its own key! To store the name of the current node, in addition to the child nodes, we can use the d3.entries helper:

function children(d) {
  return isNaN(d.value) ? d3.values(d.value) : null;
}

With this children accessor, the input to the layout must itself be an object with key and value attributes. This can be achieved by saying d3.entries(object)[0], where object is the root JSON object.

# pack.nodes(root)

Runs the pack layout, returning the array of nodes associated with the specified root node. The cluster layout is part of D3's family of hierarchical layouts. These layouts follow the same basic structure: the input argument to the layout is the root node of the hierarchy, and the output return value is an array representing the computed positions of all nodes. Several attributes are populated on each node:

  • parent - the parent node, or null for the root.
  • children - the array of child nodes, or null for leaf nodes.
  • value - the node value, as returned by the value accessor.
  • depth - the depth of the node, starting at 0 for the root.
  • x - the computed x-coordinate of the node position.
  • y - the computed y-coordinate of the node position.

# pack.links(nodes)

Given the specified array of nodes, such as those returned by nodes, returns an array of objects representing the links from parent to child for each node. Leaf nodes will not have any links. Each link is an object with two attributes:

  • source - the parent node (as described above).
  • target - the child node.

This method is useful for retrieving a set of link descriptions suitable for display, often in conjunction with the diagonal shape generator. For example:

svg.selectAll("path")
    .data(cluster.links(nodes))
  .enter().append("svg:path")
    .attr("d", d3.svg.diagonal());

# pack.value([value])

If value is specified, sets the value accessor to the specified function. If value is not specified, returns the current value accessor, which assumes that the input data is an object with a numeric value attribute:

function value(d) {
  return d.value;
}

The value accessor is invoked for each input data element, and must return a number representing the numeric value of the node. This value is used to set the area of each circle proportionally to the value. However, note that circle size is strictly comparable only to other nodes at the same depth in the hierarchy, as there is typically wasted space between packed child circles and their parent.

# pack.size([size])

If size is specified, sets the available layout size to the specified two-element array of numbers representing x and y. If size is not specified, returns the current size, which defaults to 1×1.

Clone this wiki locally