You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在D3.js中生成小倍数?2×2条形图代码无显示求助

解决D3.js 2×2小倍数条形图无内容显示的问题

我懂你这种卡壳的感觉——折腾D3做小倍数,查了一堆教程还是啥都出不来,太挫败了!咱们先从你给出的代码片段和常见坑点入手,一步步搞定这个2×2的条形图小倍数。

先排查常见的无内容原因

你代码运行没显示东西,大概率是这几个问题里的一个:

  • 数据没按分组结构处理,小倍数需要把数据拆成4组对应每个子图
  • 没正确创建子图的布局容器,或者子图的位置计算错误,内容被移出SVG视野
  • 比例尺没有针对每个子图单独设置,导致条形尺寸/位置异常(比如高度为0)
  • 代码不完整(你给的代码到var m...就断了),关键的绑定数据、绘制元素的部分缺失

完整的2×2小倍数条形图示例代码

我给你写了一个可直接运行的示例,每一步都标了注释,你可以对照着改自己的代码:

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style type="text/css">
    rect {
      transition: fill 0.3s;
    }
    rect:hover {
      fill: #2257b2;
    }
  </style>
</head>
<body>
  <script type="text/javascript">
    // ---------------------- 1. 设置参数和数据 ----------------------
    // 单个小图的尺寸
    const panelWidth = 250;
    const panelHeight = 150;
    // 小图内部边距(轴和标题的空间)
    const margin = { top: 20, right: 20, bottom: 30, left: 40 };
    // 小图之间的间距
    const panelGap = { x: 30, y: 30 };
    // 整体SVG的总尺寸(2列×2行 + 间距)
    const totalWidth = panelWidth * 2 + panelGap.x * 3;
    const totalHeight = panelHeight * 2 + panelGap.y * 3;

    // 示例数据:4组数据,对应2×2的4个小图
    const dataset = [
      { group: "组1", values: [12, 28, 18, 35] },
      { group: "组2", values: [25, 15, 30, 22] },
      { group: "组3", values: [8, 19, 27, 14] },
      { group: "组4", values: [32, 10, 21, 29] }
    ];

    // ---------------------- 2. 创建SVG容器 ----------------------
    const svg = d3.select("body")
      .append("svg")
      .attr("width", totalWidth)
      .attr("height", totalHeight);

    // ---------------------- 3. 创建小倍数容器 ----------------------
    // 为每组数据创建一个g元素(小图容器)
    const panels = svg.selectAll(".panel")
      .data(dataset)
      .enter()
      .append("g")
      .attr("class", "panel")
      .attr("transform", (d, i) => {
        // 计算每个小图的位置:2列布局,i%2是列索引,Math.floor(i/2)是行索引
        const x = panelGap.x + (i % 2) * (panelWidth + panelGap.x);
        const y = panelGap.y + Math.floor(i / 2) * (panelHeight + panelGap.y);
        return `translate(${x}, ${y})`;
      });

    // ---------------------- 4. 为每个小图绘制内容 ----------------------
    panels.each(function(d) {
      const currentPanel = d3.select(this);

      // 针对当前组的数据创建比例尺
      // X轴:条形的类别(用values的索引)
      const xScale = d3.scaleBand()
        .domain(d3.range(d.values.length))
        .range([margin.left, panelWidth - margin.right])
        .padding(0.1); // 条形之间的间距

      // Y轴:数值范围
      const yScale = d3.scaleLinear()
        .domain([0, d3.max(d.values)]) // 从0到当前组的最大值
        .range([panelHeight - margin.bottom, margin.top]); // 注意D3的Y轴是从上到下的

      // 绘制条形
      currentPanel.selectAll("rect")
        .data(d.values)
        .enter()
        .append("rect")
        .attr("x", (val, idx) => xScale(idx))
        .attr("y", val => yScale(val))
        .attr("width", xScale.bandwidth())
        .attr("height", val => panelHeight - margin.bottom - yScale(val))
        .attr("fill", "#4287f5");

      // 添加X轴
      currentPanel.append("g")
        .attr("transform", `translate(0, ${panelHeight - margin.bottom})`)
        .call(d3.axisBottom(xScale));

      // 添加Y轴
      currentPanel.append("g")
        .attr("transform", `translate(${margin.left}, 0)`)
        .call(d3.axisLeft(yScale));

      // 添加小图标题
      currentPanel.append("text")
        .attr("x", panelWidth / 2)
        .attr("y", margin.top / 2)
        .attr("text-anchor", "middle")
        .style("font-weight", "bold")
        .text(d.group);
    });
  </script>
</body>
</html>

对你的代码的调整建议

  1. 补全代码结构:你原来的代码只到var m...,要确保包含数据定义、SVG创建、小图布局、比例尺设置和元素绘制的完整流程
  2. 检查数据结构:确保你的数据是按组拆分的(比如4组,每组对应一个小图),这样才能绑定到每个小图容器上
  3. 验证位置计算:用transform定位每个小图时,要确认X/Y坐标的计算是正确的,避免小图被放到SVG外面
  4. 单独设置比例尺:每个小图的比例尺要基于当前组的数据计算,不要用全局的比例尺(除非你需要统一的刻度范围)

内容的提问来源于stack exchange,提问作者santoku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:54:50