Installations
npm install d3-flextree
Developer
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
No
Node Version
14.17.5
NPM Version
8.1.3
Statistics
327 Stars
103 Commits
45 Forks
11 Watching
11 Branches
3 Contributors
Updated on 19 Nov 2024
Languages
JavaScript (98.49%)
CSS (0.78%)
HTML (0.73%)
Total Downloads
Cumulative downloads
Total Downloads
8,259,284
Last day
-2.3%
16,176
Compared to previous day
Last week
-8.8%
92,168
Compared to previous week
Last month
23%
411,773
Compared to previous month
Last year
39.2%
3,848,702
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
D3 flextree plugin
This plugin provides a more general version of the D3 tree layout
module. Unlike tree
, this plugin
allows for nodes of variable sizes; like tree
, the algorithm is fast, running
in O(n) time.
See the demo.
flextree()
is a factory function that returns a layout instance. A
layout is a function that computes the positions of nodes in a
tree diagram. Properties attached to the layout control various parameters
of the algorithm.
Try d3-flextree in your browser.
Installing
If you use npm, npm install d3-flextree
.
Otherwise, download the latest
release.
AMD, CommonJS, and browser environments are supported.
Alternatively, you can use it straight from the jsdelivr CDN at https://cdn.jsdelivr.net/npm/d3-flextree@2.0.0/build/d3-flextree.min.js. or d3-flextree.js
Overview
Computing the layout of a tree data structure involves two steps: first, create a hierarchy from the data, and second, invoke the layout function.
In a Node environment:
1const flextree = require('d3-flextree').flextree; 2const layout = flextree(); 3const tree = layout.hierarchy({ 4 size: [1, 1], 5 children: [ 6 { size: [2, 4] }, 7 { size: [3, 1], 8 children: [ 9 { size: [4, 1] }, 10 ], 11 }, 12 ], 13}); 14layout(tree); 15tree.each(node => console.log(`(${node.x}, ${node.y})`));
In a browser, flextree
is attached to a d3
global (which is created
if necessary):
1<script src="d3-flextree.js"></script> 2<script> 3 const flextree = d3.flextree; 4 ... 5</script>
When creating the hierarchy, the library uses the children
accessor
function to determine the children of a data node. When the layout is
computed, two other accessor functions are used: nodeSize
(to get the
node sizes) and spacing
(to determine how far apart adjacent
nodes in the diagram should be placed).
The example above uses the default accessors:
1children: data => data.children, 2nodeSize: node => node.data.size, 3spacing: 0,
If the data is structured differently, the children
and nodeSize
accessors can be customized. For example, here is the same tree encoded in a
nested array structure, along with the code to compute the layout using a
spacing
function that increases the gap between more distantly related
nodes:
1const data = [ 2 1, 1, 3 [ 2, 4 ], 4 [ 3, 1, 5 [ 4, 1 ], 6 ], 7]; 8const layout = flextree({ 9 children: data => { 10 const kd = data.slice(2); 11 return kd.length ? kd : null; 12 }, 13 nodeSize: node => node.data.slice(0, 2), 14 spacing: (nodeA, nodeB) => nodeA.path(nodeB).length, 15}); 16const tree = layout.hierarchy(data); 17layout(tree); 18console.log(layout.dump(tree)); //=> prints the results
The accessors can also be set using D3-style chained methods:
1const layout = flextree() 2 .children(data => { 3 const kd = d.slice(2); 4 return kd.length ? kd : null; 5 }) 6 .nodeSize(node => node.data.slice(0, 2)) 7 .spacing((nodeA, nodeB) => nodeA.path(nodeB).length);
One thing to keep in mind is that the argument passed to the
children
accessor is a node in the data structure,
whereas the arguments to nodeSize
and spacing
are nodes of
the hierarchy.
The layout.hierarchy
method is a convenience form
of the d3.hierarchy
function, and creates a set of objects that are instances of
a class that derives from d3.hierarchy
. It's not required to
use the d3-flextree version. The following code is equivalent to
the example above, with three custom accessors. Note that the
children
accessor needs to be passed as the second argument
to the d3.hierarchy
function:
1const layout = flextree({ 2 nodeSize: node => node.data.slice(0, 2), 3 spacing: (nodeA, nodeB) => nodeA.path(nodeB).length, 4}); 5const tree = hierarchy(data, data => { 6 const kd = d.slice(2); 7 return kd.length ? kd : null; 8}); 9layout(tree);
API Reference
# flextree(accessors)
Creates a new layout with the specified accessors. Any subset of
children
, nodeSize
, and spacing
can be specified in the
argument object. If one is not specified, then the default is used:
1children: data => data.children, 2nodeSize: node => node.data.size, 3spacing: 0,
The accessors can also be changed using chained methods, for example:
1const layout = flextree() 2 .spacing((nodeA, nodeB) => nodeA.path(nodeB).length);
# layout.hierarchy(data)
Creates a new hierarchy from the data, using the children
accessors
in effect when called. This is an enhanced version of the
d3.hierarchy
function, and produces a tree of instances of a class derived from
d3.hierarchy
.
Each node of the hierarchy inherits all of the methods defined in d3.hierarchy, including:
- node.ancestors()
- node.descendants()
- node.leaves()
- node.path(target)
- node.links()
- node.sum(value)
- node.count()
- node.sort(compare)
- node.each(function)
- node.eachAfter(function)
- node.eachBefore(function)
- node.copy() - this method is re-implemented in flextree, such that it preserves the class.
In addition, each of the objects in the returned hierarchy has
several property getters. Many of these will be meaningless
until layout
is called on this tree. They include:
x
- the computed x-coordinate of the node position.y
- the computed y-coordinate of the node position.data
- reference to the original data objectnodes
- all of the nodes in this subtree (same asdescendants()
)parent
- the parent node, ornull
for the root.children
- the array of child nodes, ornull
for leaf nodes.numChildren
hasChildren
noChildren
depth
- the depth of the node, starting at 0 for the root.height
- the distance from this node to its deepest descendent, or 0 for leaf nodes.length
- number of nodes in this subtreesize
- size of this node (the values fetched by thenodeSize
accessor) as a two-element array.xSize
ySize
top
bottom
left
right
extents
- the minimumtop
andleft
, and the maximumbottom
andright
values for all of the nodes in this subtree
# layout(tree)
Computes the layout of a hierarchy. x
and y
properties are
set on each node, and many other properties useful in rendering
are available -- see the list above.
Although the layout is defined in terms of x and y, these represent an arbitrary coordinate system. For example, you can treat x as a radius and y as an angle to produce a radial rather than Cartesian layout.
# layout.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 property, whose value is either an array or null
if there
are no children:
1data => data.children
Note that unlike the other accessors, this takes a data node
as an argument. This is used only in the creation of a hierarchy,
prior to computing the layout, by the layout.hierarchy
method.
# layout.nodeSize([nodeSize])
If nodeSize is specified as a two-element array [xSize, ySize]
, then
this sets that as the fixed size for every node in the tree. If nodeSize
is a function, then that function is passed the hierarchy node as an argument,
and should return a two-element array. If nodeSize is not specified, this
returns the current setting.
The default nodeSize
assumes that a node's size is available as a
property on the data item:
1node => node.data.size
# layout.spacing([spacing])
If a spacing argument is given as a constant number, then the layout
will insert the given fixed spacing between every adjacent node.
If it is given as a function, then that function will be passed two
nodes, and should return the minimum allowable spacing between those
nodes. If spacing is not specified,
this returns the current spacing, which defaults to 0
.
To increase the spacing for nodes as the distance of their relationship increases, you could use, for example:
1layout.spacing((nodeA, nodeB) => nodeA.path(nodeB).length);
The Algorithm
The existing D3 tree layout is based on an algorithm developed originally by Reingold and Tilford in their paper from 1981, Tidier Drawings of Trees. The algorithm was improved over time by others, including Walker, in a paper in 1989, A Node-Positioning Algorithm for General Trees, and the latest improvement by Bucheim, Junger, and Leipert in 2002, described in their paper, Improving Walker's Algorithm to Run in Linear Time.
A limitation of that algorithm is that it applies to trees in which all of the nodes are the same size. This is adequate for many applications, but a more general solution, allowing variable node sizes, is often preferable.
In a paper from 2013, A.J. van der Ploeg enhanced the algorithm to allow for variable-sized nodes, while keeping its linear runtime nature. He described the algorithm in his paper, Drawing Non-layered Tidy Trees in Linear Time. The author also provided a working Java application on GitHub at cwi-swat/non-layered-tidy-trees.
This module is a port from that Java code into JavaScript.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: Do What The F*ck You Want To Public License: LICENSE:0
Reason
Found 2/25 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
Project has not signed or included provenance with any releases.
Details
- Warn: release artifact 1.0.2 not signed: https://api.github.com/repos/Klortho/d3-flextree/releases/3265542
- Warn: release artifact 1.0.2 does not have provenance: https://api.github.com/repos/Klortho/d3-flextree/releases/3265542
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 8 are checked with a SAST tool
Reason
37 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-6chw-6frg-f759
- Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw
- Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx
- Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-rq8g-5pc5-wrhr
- Warn: Project is vulnerable to: GHSA-36jr-mh4h-2g58
- Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2
- Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq
- Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp
- Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj
- Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546
- Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx
- Warn: Project is vulnerable to: GHSA-896r-f27r-55mw
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574
- Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm
- Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695
- Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw
- Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9
- Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m / GHSA-xvch-5gv4-984h
- Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9
- Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp
- Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4
- Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7
- Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7
- Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Score
1.5
/10
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More