返回

揭秘 d3.js:绘制股权穿透图的终极指南

前端

手把手教你使用 d3.js 画一个股权穿透图

引言:

股权穿透图是一种强大的工具,用于可视化公司所有权结构的复杂性。它们在金融分析、企业治理和并购交易中至关重要。虽然网上不乏股权穿透图的例子,但它们往往设计粗劣,缺乏交互性。

本文将指导您使用流行的 d3.js 库(v7)从头开始创建交互式股权穿透图。我们将重点关注简洁性和易用性,同时提供丰富的功能,例如“全部展开”和“全部收缩”操作。

先决条件:

在开始之前,您需要熟悉以下内容:

  • HTML、CSS 和 JavaScript 的基础知识
  • d3.js 库(v7)
  • JSON 数据格式

步骤 1:设置数据

我们的股权穿透图将基于 JSON 数据,其中包含公司之间的所有权关系。数据结构如下:

{
  "nodes": [
    { "id": "A", "name": "公司 A" },
    { "id": "B", "name": "公司 B" },
    { "id": "C", "name": "公司 C" }
  ],
  "links": [
    { "source": "A", "target": "B", "value": 50 },
    { "source": "A", "target": "C", "value": 25 }
  ]
}

nodes 数组中,每个节点代表一家公司,具有唯一的 ID 和名称。在 links 数组中,每条边表示两个节点之间的所有权关系,具有源节点、目标节点和 value(所有权百分比)。

步骤 2:创建 SVG Canvas

在 HTML 文档中,创建一个 SVG canvas,它将充当我们的绘图区域:

<div id="chart"></div>

在 JavaScript 中,使用 d3.js 选择并创建 SVG canvas:

const svg = d3
  .select("#chart")
  .append("svg")
  .attr("width", 800)
  .attr("height", 600);

步骤 3:定义布局

d3.js 提供了各种布局,用于组织图形元素。对于股权穿透图,我们将使用树形布局:

const tree = d3.tree()
  .size([800, 600]);

布局将我们的节点和边组织成一个分层的结构。

步骤 4:绘制节点和边

接下来,我们将绘制节点和边:

const nodes = tree(data).descendants();
const links = tree.links(nodes);

const nodeGroup = svg.append("g")
  .attr("class", "nodes")
  .selectAll("g")
  .data(nodes)
  .enter()
  .append("g");

nodeGroup.append("circle")
  .attr("r", 10)
  .attr("fill", "#fff")
  .attr("stroke", "#000");

nodeGroup.append("text")
  .attr("dy", -3)
  .attr("text-anchor", "middle")
  .text(d => d.data.name);

const linkGroup = svg.append("g")
  .attr("class", "links")
  .selectAll("path")
  .data(links)
  .enter()
  .append("path")
  .attr("d", d3.linkHorizontal()
  .x(d => d.x)
  .y(d => d.y));

步骤 5:添加交互性

最后,我们添加交互性,允许用户展开和收缩子节点:

const toggleNode = (node) => {
  node.children
    ? node._children = node.children
    : node.children = node._children;
  node.children
    ? node.children.forEach(toggleNode)
    : null;
};

nodeGroup.on("click", d => toggleNode(d));

结论:

我们已经构建了一个功能齐全的股权穿透图,使用最新的 d3.js 技术并具有丰富的交互性。这种方法不仅简单易用,而且还提供了广泛的定制选项。通过使用 JSON 数据,我们可以轻松更新图表的底层数据,从而使其保持最新和准确。