如何使用D3 v7实现带下拉菜单的多折线图并修复运行报错
问题原因及修复方案
核心报错根源
Cannot read property 'year' of undefined报错来自三个可明确的代码错误:
d3.line()调用逻辑错误:d3.line()生成的是需要接收数据数组作为入参的函数,你当前代码中valueLine(([, values]) => values)是把箭头函数本身传给了valueLine,而非实际的数值数组,导致生成路径时拿不到点数据。- 字段名不匹配:你提到数据集的数值字段是
wvalues,但代码里全部写为wvalue,少了末尾的s,读取字段时会直接拿到undefined。 - 缺少类型转换:
d3.csv默认读取的所有字段都是字符串类型,你没有手动将year、wvalues转为数值类型,即使后续逻辑正确也会出现坐标轴映射错误。
分步修复方案
步骤1:新增数据类型转换并修正字段名
在d3.csv读取数据时新增类型转换逻辑,同时把全代码中所有wvalue替换为wvalues,包括y轴定义域、line生成器的y访问器:
// 读取数据时转换类型 d3.csv('15/data.csv', function(d) { return { year: +d.year, // 转数值 state: d.state, wvalues: +d.wvalues, // 转数值 lvalues: d.lvalues } }).then(function (data) { // y轴定义域同步修正字段名 y.domain([ d3.min([0,d3.min(data,function (d) { return d.wvalues })]), d3.max([0,d3.max(data,function (d) { return d.wvalues })]) ]); // 剩余原有逻辑 })
步骤2:修正line生成器调用逻辑
valueLine需要接收对应单条折线的所有年份数据数组作为入参,调整路径生成的代码:
// line生成器同步修正字段名 var valueLine = d3.line() .x(function(d) { return x(d.year); }) .y(function(d) { return y(d.wvalues); })
步骤3:修正初始渲染和更新逻辑的参数传递
// 修正后的initialGraph var initialGraph = function(legis){ var selectLegis = nest.filter(([key, ]) => key == legis) var selectLegisGroups = svg.selectAll(".legisGroups") // d3.groups返回的元素是[key, values]数组,用第一个元素作为key即可 .data(selectLegis, d => d[0]) .enter() .append("g") .attr("class", "legisGroups") var initialPath = selectLegisGroups.selectAll(".line") .data(([, values]) => values) .enter() .append("path") // 二级分组的第二个元素就是单条折线对应的所有年份数据数组 .attr("d", d => valueLine(d[1])) .attr("class", "line") } // 修正后的updateGraph var updateGraph = function(legis){ var selectLegis = nest.filter(([key, ]) => key == legis) var selectLegisGroups = svg.selectAll(".legisGroups") .data(selectLegis) selectLegisGroups.selectAll("path.line") .data(([, values]) => values) .transition() .duration(1000) .attr("d", d => valueLine(d[1])) }
内容的提问来源于stack exchange,提问作者Gregg
相关产品推荐
相关产品推荐

