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
相关产品推荐
相关产品推荐

