Gathering detailed insights and metrics for @d3fc/d3fc-label-layout
Gathering detailed insights and metrics for @d3fc/d3fc-label-layout
Gathering detailed insights and metrics for @d3fc/d3fc-label-layout
Gathering detailed insights and metrics for @d3fc/d3fc-label-layout
A collection of components that make it easy to build interactive charts with D3
npm install @d3fc/d3fc-label-layout
Typescript
Module System
Node Version
NPM Version
@d3fc/d3fc-chart@5.1.9
Updated on Jul 30, 2024
@d3fc/d3fc-webgl@3.2.1
Updated on Jul 30, 2024
@d3fc/d3fc-series@6.1.3
Updated on Jul 30, 2024
@d3fc/d3fc-annotation@3.0.16
Updated on Jul 30, 2024
d3fc@15.2.13
Updated on Jul 30, 2024
d3fc@15.2.12
Updated on Jul 02, 2024
HTML (78.71%)
JavaScript (13.65%)
TypeScript (5.92%)
Shell (1.72%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1,330 Stars
1,351 Commits
197 Forks
41 Watchers
18 Branches
55 Contributors
Updated on Jul 13, 2025
Latest Version
7.0.4
Package Id
@d3fc/d3fc-label-layout@7.0.4
Unpacked Size
230.78 kB
Size
194.09 kB
File Count
25
NPM Version
lerna/8.1.2/node@v21.7.3+x64 (linux)
Node Version
21.7.3
Published on
Jun 13, 2024
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
2
3
A D3 layout that places labels avoiding overlaps, with strategies including simulated annealing, greedy and a strategy that removes overlapping labels.
For a live demo, see the GitHub Pages site.
1npm install @d3fc/d3fc-label-layout
The label layout component provides a mechanism for arranging child components based on their rectangular bounding boxes. It is typically used to render labels on maps or charts. A layout strategy is passed to the component in order to arrange the child rectangles avoiding collisions or remove overlaps.
1import { layoutTextLabel, layoutGreedy, 2 layoutLabel, layoutRemoveOverlaps } from 'd3fc-label-layout'; 3import { select } from 'd3-selection'; 4 5const labelPadding = 2; 6 7// the component used to render each label 8const textLabel = layoutTextLabel() 9 .padding(labelPadding) 10 .value(d => d.properties.name); 11 12// a strategy that combines simulated annealing with removal 13// of overlapping labels 14const strategy = layoutRemoveOverlaps(layoutGreedy()); 15 16// create the layout that positions the labels 17const labels = layoutLabel(strategy) 18 .size((d, i, g) => { 19 // measure the label and add the required padding 20 const textSize = g[i].getElementsByTagName('text')[0].getBBox(); 21 return [textSize.width + labelPadding * 2, textSize.height + labelPadding * 2]; 22 }) 23 .position(d => projection(d.geometry.coordinates)) 24 .component(textLabel); 25 26// render! 27svg.datum(places.features) 28 .call(labels);
The above snippet is taken from a complete example showing how this label layout component can be used to arrange labels on a map.
For integration with charts the label layout component exposes xScale
and yScale
properties, as shown in this example.
# fc.layoutLabel(strategy)
Constructs a new label layout with the given strategy. The label layout creates an array of rectangle bounding boxes which are passed to the strategy, which will typically move the boxes in order to minimise overlaps. Once the layout is complete a data join is used to construct a containing g
element for each item in the bound array, and the component supplied to the layout is 'call'-ed on each element.
Each g
element has the following properties set:
layout-width
, layout-height
- the width and height of this label, as provided by the size
property.display
- set to inherit
or hidden
, based on whether the strategy has hidden this label.anchor-x
, anchor-y
- the original label location in relative coordinates to the this g
element.# 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 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.
# layoutLabel.position(accessor)
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]
.
# layoutLabel.component(component)
Specified the component that is used to render each label.
# layoutLabel.xScale(scale) # 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.
The label component uses a strategy in order to re-locate labels to avoid collisions, or perhaps hide those that overlap.
The strategy is supplied an array of objects that describe the initial location of each label, as obtained via the position
and size
properties of layout
.
Each object has the following structure:
{
hidden: ...,
x: ...,
y: ...,
width: ...,
height: ...,
}
The strategy should return an array of objects indicating the placement of each label.
The greedy strategy is a very fast way of reducing label overlap. It adds each label in sequence, selecting the position where the label has the lowest overlap with already added rectangles and is inside the container.
# fc.layoutGreedy()
Constructs a greedy strategy.
# layoutGreedy.bounds(rect)
Optionally specifies a bounding region, as a rectangle with properties of x
, y
, width
and height
. The strategy will try to keep labels within the bounds.
The simulated annealing strategy runs over a set number of iterations, choosing a different location for one label on each iteration. If that location results in a better result, it is saved for the next iteration. Otherwise, it is saved with probability inversely proportional with the iteration it is currently on. This helps it break out of local optimums, hopefully producing better output. Because of the random nature of the algorithm, it produces variable output.
# fc.layoutAnnealing()
Constructs an annealing strategy.
# layoutAnnealing.bounds(rect)
Optionally specifies a bounding region, as a rectangle with properties of x
, y
, width
and height
. The strategy will try to keep labels within the bounds.
# layoutAnnealing.temperature(integer)
# layoutAnnealing.cooling(integer)
The temperature parameter indicates the initial 'number' to use for the random probability calculation, and cooling defines the delta of the temperature between iterations. The algorithm runs for Math.ceil(temperature / cooling)
iterations.
This strategy doesn't re-position labels to reduce overlaps, instead it removes overlapping labels. This is performed iteratively, with the labels that have the greatest area of overlap removed first.
# fc.layoutRemoveOverlaps(strategy)
Constructs a removeOverlaps strategy, adapting the supplied strategy in order to remove overlaps after it has been executed.
This is a simple component that renders a label:
This component uses the layout-width
and layout-height
properties of its parent element to set its own width and height. It also uses the anchor-x
and anchor-y
properties to place the circular anchor. These properties are all set by the label layout as described above.
# fc.layoutTextLabel()
Constructs a text label component.
# textLabel.labelPadding(number)
Specifies the padding around the text.
# layoutTextLabel.value(accessor)
Specifies the text rendered by this label as an accessor function.
No vulnerabilities found.
Reason
all changesets reviewed
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
no binaries found in the repo
Reason
dependency not pinned by hash detected -- score normalized to 5
Details
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
detected GitHub workflow tokens with excessive permissions
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
16 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
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