超实用D3.js实战:零基础掌握旭日图与树状图可视化

超实用D3.js实战:零基础掌握旭日图与树状图可视化

【免费下载链接】d3 Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada: 【免费下载链接】d3 项目地址: https://gitcode.com/gh_mirrors/d3/d3

你还在为复杂层级数据发愁?产品分类、组织架构、文件系统的层级关系是不是总让你眼花缭乱?本文将用最通俗的语言,带你一步到位掌握D3.js中两种顶级分层数据可视化方案——树状图(Tree)和旭日图(Sunburst),从此让层级数据一目了然。读完本文你将获得:分层数据转换技巧、两种布局完整实现代码、3类场景最佳选择指南,以及5个实战优化技巧。

数据准备:从表格到层级结构

所有分层可视化的第一步都是将原始数据转换为层级结构。D3.js提供了d3.stratify()工具,能轻松将CSV表格数据转换为可视化所需的层级格式。以下是将产品分类数据转换为层级结构的示例:

// 假设我们有这样的产品分类数据
const productData = [
  { name: "电子产品", parent: "" },
  { name: "手机", parent: "电子产品" },
  { name: "笔记本", parent: "电子产品" },
  { name: "智能手机", parent: "手机" },
  { name: "功能机", parent: "手机" },
  { name: "轻薄本", parent: "笔记本" },
  { name: "游戏本", parent: "笔记本" }
];

// 使用stratify转换为层级结构
const root = d3.stratify()
  .id(d => d.name)
  .parentId(d => d.parent)
  (productData);

这个过程就像给数据"搭骨架",转换后的层级结构可以直接用于树状图和旭日图的绘制。转换原理如图所示:

分层数据转换示意图

树状图实现:清晰展示层级关系

树状图(Tree)是最经典的层级数据可视化方式,通过节点和连接线清晰展示父子关系,特别适合展示具有明确层级的结构如组织架构。D3.js的tree布局采用Reingold-Tilford算法,能自动计算节点最优位置,生成紧凑美观的树状图。

基础实现代码

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
  <style>
    .node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; }
    .node text { font: 12px sans-serif; }
    .link { fill: none; stroke: #ccc; stroke-width: 1.5px; }
  </style>
</head>
<body>
  <svg width="600" height="400"></svg>
  <script>
    // 前面准备的层级数据root
    const svg = d3.select("svg"),
          width = +svg.attr("width"),
          height = +svg.attr("height"),
          g = svg.append("g").attr("transform", "translate(40,0)");

    // 创建树状图布局
    const tree = d3.tree().size([height - 160, width - 120]);
    
    // 计算节点位置
    tree(root);
    
    // 绘制连接线
    const link = g.selectAll(".link")
      .data(root.links())
      .enter().append("path")
        .attr("class", "link")
        .attr("d", d3.linkHorizontal()
          .x(d => d.y)
          .y(d => d.y));
    
    // 绘制节点
    const node = g.selectAll(".node")
      .data(root.descendants())
      .enter().append("g")
        .attr("class", d => "node" + (d.children ? " node--internal" : " node--leaf"))
        .attr("transform", d => `translate(${d.y},${d.x})`);
    
    node.append("circle").attr("r", 4.5);
    
    node.append("text")
        .attr("dy", 3)
        .attr("x", d => d.children ? -10 : 10)
        .style("text-anchor", d => d.children ? "end" : "start")
        .text(d => d.id);
  </script>
</body>
</html>

关键配置项

树状图布局提供了多种自定义方式:

下面是一个设置不同节点间距的示例:

// 为不同层级设置不同间距
tree.separation((a, b) => a.parent === b.parent ? 1 : 2 / a.depth);

树状图特别适合展示深度较大的层级结构,如公司组织架构,能清晰展示从顶层到基层的完整汇报关系。

旭日图实现:面积编码的层级可视化

旭日图(Sunburst)是一种环形的空间填充可视化,通过弧度和半径展示层级关系,同时用面积大小表示数值。在D3.js中,旭日图通过partition布局结合极坐标转换实现,特别适合展示具有数值权重的层级数据,如产品销售额占比分析。

基础实现代码

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
  <style>
    .sunburst path { stroke: #fff; }
    .sunburst text { font: 10px sans-serif; fill: white; }
  </style>
</head>
<body>
  <svg width="600" height="600"></svg>
  <script>
    // 为数据添加数值属性(如销售额)
    root.sum(d => d.value || 1);
    
    const svg = d3.select("svg"),
          width = +svg.attr("width"),
          height = +svg.attr("height"),
          radius = Math.min(width, height) / 2,
          g = svg.append("g").attr("transform", `translate(${width/2},${height/2})`);
    
    // 创建分区布局
    const partition = d3.partition()
        .size([2 * Math.PI, radius]);
    
    // 计算布局
    partition(root);
    
    // 生成圆弧路径生成器
    const arc = d3.arc()
        .startAngle(d => d.x0)
        .endAngle(d => d.x1)
        .innerRadius(d => d.y0)
        .outerRadius(d => d.y1);
    
    // 绘制旭日图
    const path = g.selectAll("path")
        .data(root.descendants())
        .enter().append("path")
        .attr("d", arc)
        .style("fill", d => {
          // 根据层级生成不同颜色
          while (d.depth > 1) d = d.parent;
          return ["#ff6b6b", "#4ecdc4", "#ffd166", "#06d6a0"][d.data.index % 4];
        })
        .style("stroke", "#fff")
        .on("mouseover", function(event, d) {
          // 添加交互效果
          d3.select(this).style("opacity", 0.8);
        })
        .on("mouseout", function(event, d) {
          d3.select(this).style("opacity", 1);
        });
    
    // 添加标签
    g.selectAll("text")
        .data(root.descendants().filter(d => (d.y0 + d.y1) / 2 * (d.x1 - d.x0) > 10))
        .enter().append("text")
        .attr("transform", d => {
          const x = (d.x0 + d.x1) / 2 * 180 / Math.PI;
          const y = (d.y0 + d.y1) / 2;
          return `rotate(${x - 90}) translate(${y},0) rotate(${x < 180 ? 0 : 180})`;
        })
        .attr("dy", "0.35em")
        .attr("text-anchor", "middle")
        .text(d => d.id);
  </script>
</body>
</html>

关键配置项

分区布局的主要配置包括:

旭日图通过面积直观展示每个节点的权重,非常适合展示资源分配、销售额占比等带有数值属性的层级数据。下图展示了不同版本的包围布局效果对比:

包围布局v3版本 包围布局v4版本

两种布局的对比与最佳实践

特性树状图(Tree)旭日图(Sunburst)
空间效率低(需要大量垂直/水平空间)高(环形紧凑布局)
层级感知优秀(清晰的父子关系)中等(内圈为父,外圈为子)
数值比较困难(主要展示结构)优秀(面积直观反映数值)
深度适应性适合深层级(可滚动)适合中层级(过深会拥挤)
交互复杂度简单(平移缩放)中等(需要处理环形交互)

场景选择指南

  1. 组织架构展示:优先选择树状图,清晰展示汇报关系
  2. 磁盘空间分析:优先选择旭日图,直观比较文件大小占比
  3. 产品分类浏览:两者皆可,树状图适合分类导航,旭日图适合热门品类分析
  4. 时间线层级数据:建议使用树状图,可自然展示时间流向

性能优化技巧

  1. 数据过滤:对深度过大的层级数据进行截断,参考分层数据处理
  2. 懒加载:初始只渲染顶层节点,交互时再加载子节点
  3. 样式优化:减少节点边框宽度,使用半透明色代替实色
  4. 事件委托:对大量节点使用事件委托优化性能
  5. WebWorker:复杂布局计算放在WebWorker中执行,避免阻塞主线程

总结与进阶学习

树状图和旭日图各有所长,关键是根据数据特性和业务需求选择合适的可视化方式。树状图在展示层级关系方面具有天然优势,而旭日图则在数值比较和空间效率上表现突出。

想要深入学习D3.js分层可视化,可以继续探索:

D3.js的分层可视化模块为我们处理复杂层级数据提供了强大工具,掌握这些技能将让你的数据故事更具说服力。现在就动手尝试,将你手中的层级数据转换为直观易懂的可视化作品吧!

更多D3.js高级技巧和最佳实践,请参考官方文档社区教程。如果觉得本文有帮助,别忘了点赞收藏,关注获取更多数据可视化实战教程!

【免费下载链接】d3 Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada: 【免费下载链接】d3 项目地址: https://gitcode.com/gh_mirrors/d3/d3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值