@d3fc/d3fc-label-layout

中文文档
7.0.4发布于 2024/06/13MITESM + CJS近 30 天下载 6.3万

A D3 layout that places labels avoiding overlaps using either a greedy or simulated annealing strategy

原始使用文档
文档目录5 节
  1. Installing
  2. API Reference
  3. Label
  4. Strategy
  5. Text Label

d3fc-label-layout

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.

Main D3FC package

Installing

npm install @d3fc/d3fc-label-layout

API Reference

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.

import { layoutTextLabel, layoutGreedy,
    layoutLabel, layoutRemoveOverlaps } from 'd3fc-label-layout';
import { select } from 'd3-selection';

const labelPadding = 2;

// the component used to render each label
const textLabel = layoutTextLabel()
  .padding(labelPadding)
  .value(d => d.properties.name);

// a strategy that combines simulated annealing with removal
// of overlapping labels
const strategy = layoutRemoveOverlaps(layoutGreedy());

// create the layout that positions the labels
const labels = layoutLabel(strategy)
    .size((d, i, g) => {
        // measure the label and add the required padding
        const textSize = g[i].getElementsByTagName('text')[0].getBBox();
        return [textSize.width + labelPadding * 2, textSize.height + labelPadding * 2];
    })
    .position(d => projection(d.geometry.coordinates))
    .component(textLabel);

// render!
svg.datum(places.features)
     .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.

Label

# 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.

Strategy

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.

Greedy

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.

Simulated Annealing

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.

Remove overlaps

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.

Text Label

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.

版本与发布记录

@d3fc/d3fc-label-layout 共发布 18 个版本,首次发布于 2018/08/02;过去 12 个月发布了 0 个版本。

版本发布日期距今
7.0.4latest2024/06/132 年前
7.0.32020/09/246 年前
7.0.22020/09/166 年前
7.0.12020/07/146 年前
7.0.02020/04/166 年前
6.1.02020/03/196 年前

关于 @d3fc/d3fc-label-layout 的常见问题

@d3fc/d3fc-label-layout 是什么?

A D3 layout that places labels avoiding overlaps using either a greedy or simulated annealing strategy

如何安装 @d3fc/d3fc-label-layout?

在项目目录运行 npm install @d3fc/d3fc-label-layout,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:d3-array(*)、d3-scale(*)、d3-selection(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@d3fc/d3fc-label-layout 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/d3fc__d3fc-label-layout 是否存在。

@d3fc/d3fc-label-layout 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@d3fc/d3fc-label-layout 可以商用吗?

@d3fc/d3fc-label-layout 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@d3fc/d3fc-label-layout 的下载量有多少?

根据 npm 官方下载统计,@d3fc/d3fc-label-layout 在 2026/10/11 – 2026/11/09 这 30 天内被下载 62,529 次,日均约 2,084 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@d3fc/d3fc-label-layout 还在维护吗?

最新版本 7.0.4 发布于 2024/06/13(2 年前);至今共发布 18 个版本,其中过去 12 个月发布了 0 个;首次发布于 2018/08/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。