Label outside arc (Pie chart) d3.js

在数据可视化中,饼图是一种常见的可视化类型。但是,在标记每个扇形的名称/值时,有时候默认的标签放置方式(内部)不足以清晰地传达信息。这时候,将标签放置在圆弧外部可以提高可读性和美观性。

问题描述

我们有一个简单的d3.js 饼图:

--- ---- - ---- --- --- ----

--- ----- - ----
--- ------ - ----
--- ------ - --------------- ------- - --

--- --- - -----------------
  --------------
  -------------- ------
  --------------- -------
  ------------
  ------------------ ------------ - ----- - - - --- - ------ - - - -----

--- ----- - -----------------
  -------------
  ----------------------------

--- --- - --------
  -----------
  ------------------ - ------ -- ---

--- ---- - --------
  ------------------- - ---
  ----------------

--- ----- - --------
  ------------------- - ---
  ------------------- - ----

--- --- - ---------------------
  ----------------
  --------------------
  -------------- -------

------------------
  ---------- -----
  -------------- ----------- - ------ -------------- ---

------------------
  ------------------ ----------- - ------ ------------ - ----------------- - ---- --
  ----------- ---------
  ----------------- - ------ ------- ---

但是,我们可以看到标签(数字)被放置在扇形内,这样会导致一些问题:

  • 标签重叠:当有多个相邻的小扇形时,标签可能会重叠并变得难以辨认。
  • 不清晰:放在内部的标签面积很小,字体也变得很小,难以阅读。

因此,我们需要将标签放在圆弧外部。

解决方案

为了将标签放置在圆弧外部,我们需要计算每个扇形的中心点,并使用该中心点作为标签的位置。为此,我们需要使用d3.arc()函数来计算圆弧上的点坐标。

首先,在上述代码中添加以下代码:

--- -------- - --------
    ------------------- - ----
    ------------------- - -----

这里我们定义了一个新的arc对象outerArc。这个对象的innerRadius和outerRadius都设置为1.2倍的radius。这意味着它的大小与主arc相同,但是半径增加了20%,使得它的位置更靠近圆周。

修改现有的代码,以将标签放置在圆弧外部:

------------------
  ------------------ ----------- -
    --- --- - ---------------------
    ------ - ------ - ------------ - ------- - --- - ------
    ------ ------------- --- -----
  --
  ----------- --------
  -------------------- ----------- -
    ------ ----------- - ------- - --------------
  --
  ----------------- - ------ ------- ---

这里我们使用outerArc.centroid(d)计算圆弧上的点,并将其作为标签位置。然后,我们根据弧度值的大小(中间角)将标签放置在圆弧左侧或右侧。

具体而言,我们使用了以下函数来计算扇形的中心角度:

-------- ----------- -
  ------ ------------ - ----------- - -

- ----------------------------------------------------------- --------
---------------------------------------------------------------------------------------