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

D3.js开发福布斯百强企业交互式条形图报data未定义错误

报错原因与代码问题排查

核心报错data not defined根因

d3.csv()是异步请求,传入.then()的回调函数里的data是回调作用域的局部变量,定义在全局的update()函数访问不到这个局部变量,所以执行到d3.max(data, d => d[xValue])时会找不到data对象。
修复方式:在d3.csv调用之前的全局作用域先声明存储数据的变量:

let allData = null

然后在d3.csv的回调里,完成数据类型转换后把处理好的数据赋值给这个全局变量,再调用update:

d3.csv("data/data_clean.csv").then(data => {
    data.forEach(d => {
        d.sales_usd_billion = Number(d.sales_usd_billion)
        d.profit_usd_billion = Number(d.profit_usd_billion)
        d.rank = Number(d.rank) // 原代码漏了rank的类型转换,排序会出现异常
    })
    allData = data
    update()
})

后续update函数里所有用到data的位置,全部替换成allData即可解决这个报错。


其他现存代码问题

  • 坐标轴组变量名写错:提前定义的坐标轴组是xAxisGroup、yAxisGroup,但update函数里写的是xAxis.transition()、yAxis.transition(),变量名不匹配会触发新的未定义报错,需要把对应位置的变量名改对。
  • 排序逻辑位置错误:当前代码先给x、y比例尺设置domain,再对数据排序,排序后的顺序不会同步到比例尺定义域,条形顺序不会随排序更新,需要把排序逻辑移到设置x、y.domain()之前执行。
  • 条形图渲染逻辑存在多处错误:
    • 没有定义rects选择集,直接调用rects.enter()会报错,需要先通过selectAll绑定数据生成选择集
    • 条形宽度取值用了未定义的value变量,应该替换成前面获取的当前指标变量xValue
    • 条形高度写死为4,会导致条形挤在一起,应该用y比例尺的y.bandwidth()获取每个条形的预留高度,可适当减去边距做留白
    • 没有处理更新、退出的选择集,切换指标时旧条形不会更新,只会不断追加新矩形,需要补上merge、remove逻辑
  • y轴band比例尺没有设置padding,条形之间没有间隙,可读性差
  • x轴标签没有动态更新逻辑,切换销售额、利润指标时,x轴标题不会同步变化
  • 漏了rank字段的类型转换,csv读入的rank默认是字符串类型,直接做减法排序会出现结果异常,需要在数据预处理阶段把rank转成数字类型。

修复后的核心update函数参考

function update() {
    const t = d3.transition().duration(750)
    // 获取当前选中指标
    const xValue = $("#var-select").val()
    // 先按当前指标排序
    allData.sort((a,b) => b[xValue] - a[xValue])
    // 再设置比例尺domain
    x.domain([0, d3.max(allData, d => d[xValue])])
    y.domain(allData.map(d => d.company)).padding(0.2) // 加20%的条间距
    // 更新坐标轴
    xAxisCall.scale(x)
    xAxisGroup.transition(t).call(xAxisCall)
    yAxisCall.scale(y)
    yAxisGroup.transition(t).call(yAxisCall)
    // 动态更新x轴标签
    d3.select(".x.axis-label").text(xValue === "sales_usd_billion" ? "销售额(十亿美元)" : "利润(十亿美元)")
    // 渲染条形,处理enter/update/exit全流程
    const rects = g.selectAll("rect.bar")
        .data(allData, d => d.company) // 用公司名做匹配key,保证动画过渡正确
    // 删除退出的旧元素
    rects.exit().remove()
    // 新增元素+合并更新集,做过渡动画
    rects.enter().append("rect")
        .attr("class", "bar")
        .attr("y", d => y(d.company))
        .attr("x", 0)
        .attr("fill", "steelblue")
        .merge(rects)
        .transition(t)
            .attr("y", d => y(d.company))
            .attr("width", d => x(d[xValue]))
            .attr("height", y.bandwidth())
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:45:36