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

d3js v7绘制柱状图报<rect> height属性期望长度为NaN错误

d3 v7 柱状图渲染报错<rect> attribute height: Expected length, "NaN" 排查方案

问题背景

在大学项目中参考Blocks示例使用d3 v7开发柱状图时,代码运行后仅渲染出空的坐标轴框架,无柱形显示、坐标轴无刻度,控制台抛出高度属性为NaN的错误,初步怀疑问题出在数据读取环节。

现有实现代码

var margin = {top: 5, right:10, bottom:5, left:10},
    width = 575 - margin.left - margin.right,
    height = 200 - margin.top - margin.bottom;

// set the ranges
var x = d3.scaleBand()
          .range([0, width])
          .padding(0.1);
var y = d3.scaleLinear()
          .range([height, 0]);
          
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("#bar").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", 
          "translate(" + margin.left + "," + margin.top + ")");

// get the data
d3.csv("canton_pop.csv").then(function(data) {

  // format the data
  data.forEach(function(d) {
    d.Population = +d.Population;
  });

  // Scale the range of the data in the domains
  x.domain(data.map(function(d) { return d.Canton; }));
  y.domain([0, d3.max(data, function(d) { return d.Population; })]);

  // append the rectangles for the bar chart
  svg.selectAll(".bar_chart")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar_chart")
      .attr("x", function(d) { return x(d.Canton); })
      .attr("width", x.bandwidth())
      .attr("y", function(d) { return y(d.Population); })
      .attr("height", function(d) { return height - y(d.Population); });

  // add the x Axis
  svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  // add the y Axis
  svg.append("g")
      .call(d3.axisLeft(y));

});

所用canton_pop.csv文件内容

Canton;Population
Zürich;1553423
Bern;1043132
Luzern;416347
Uri;36819
Schwyz;162157
Obwalden;38108
Nidwalden;43520
Glarus;40851
Zug;128794
Fribourg;325496
Solothurn;277462
Basel-Stadt;196735
Basel-Landschaft;290969
Schaffhausen;83107
Appenzell Ausserrhoden;55309
Appenzell Innerrhoden;16293
St. Gallen;514504
Graubünden;200096
Aargau;694072
Thurgau;282909
Ticino;350986
Vaud;814762
Valais;348503
Neuchâtel;175894
Genève;506343
Jura;73709

故障根因

默认d3.csv()方法仅支持按逗号,分隔的CSV文件解析,你提供的CSV文件使用分号;作为字段分隔符,导致解析失败:

  • 每一行数据会被识别为单个整行字符串,无法拆分出Canton、Population两个字段
  • 代码中读取d.Population得到undefined,转数字后为NaN,传入y比例尺计算得到无效的坐标、高度值,触发控制台报错
  • 读取d.Canton同样得到undefined,x比例尺拿不到分类值,无法渲染坐标轴刻度,柱形也因属性无效无法显示

修复方案

二选一即可:

  • 方案1:修改CSV文件,将所有分号;替换为逗号,,现有代码无需改动即可正常运行
  • 方案2:保留现有分号分隔的CSV文件,改用d3的自定义分隔符DSV解析方法加载数据,将原代码中d3.csv("canton_pop.csv")替换为d3.dsv(';', "canton_pop.csv"),其余绘图逻辑完全不需要调整。修改后的数据加载段代码示例:
// 仅修改加载方法,其余逻辑保持不变
d3.dsv(';', "canton_pop.csv").then(function(data) {

  // format the data
  data.forEach(function(d) {
    d.Population = +d.Population;
  });

  // Scale the range of the data in the domains
  x.domain(data.map(function(d) { return d.Canton; }));
  y.domain([0, d3.max(data, function(d) { return d.Population; })]);

  // 后续绘制矩形、坐标轴的代码和原来完全一致
  svg.selectAll(".bar_chart")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar_chart")
      .attr("x", function(d) { return x(d.Canton); })
      .attr("width", x.bandwidth())
      .attr("y", function(d) { return y(d.Population); })
      .attr("height", function(d) { return height - y(d.Population); });

  svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  svg.append("g")
      .call(d3.axisLeft(y));
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 04:01:13