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

使用D3.js加载自定义JSON绘制地图时遇TypeError错误求助

问题

尝试将自定义JSON数据加载到D3.js地图中时,持续报错:TypeError: cannot read properties of undefined。使用自定义JSON数据时无法完成映射,似乎无法正确读取yearninteenthirtyeight字段;但使用FreeCodeCamp的示例数据集并读取bachelorsOrHigher字段时,数据能正常加载。多次修改数据集无效,求解决方法。

JS代码

const colors = new Array("#e0f7ff","#b6e2ff","#87c4ff","#5d9eff","#007bff");

// -- GET FILES -- //
let gbCounts = "自定义JSON数据地址"
let countyGeoFile = "FreeCodeCamp地理数据地址"

let gbCountsData
let countyGeoData

// -- LOAD MAP -- //
let map = d3.select('#map')

let drawMap = () => {

    var colorScale = d3
        .scaleThreshold()
        .domain([0, 10, 30, 100, 220])
        .range(colors);


    map.selectAll('path')
        .data(countyGeoData.features)
        .enter()
        .append('path')
        .attr('d', d3.geoPath())
        .attr("stroke", "#333")
        .attr('class', 'county')
        .attr("fill", (d, i) => { //d is a county data item
            //get ID of current data element
            let currentID = d.id;
            // console.log(i, currentID)
            //find education that matches id
            let county = gbCountsData.find((item) => {
                if (item.fips === currentID) {
                    // console.log(item.state)
                    return item;
                } 
            })
            
            return colorScale(county.yearninteenthirtyeight);
        })
}

// -- LOAD MAP DATA -- //
d3.json(gbCounts).then(
    (data, error) => {
        if(error) {
            console.log(error);
        } else {
            // if no error, load data
            gbCountsData = data;
            console.log(gbCountsData)

            // load map after data is loaded
            d3.json(countyGeoFile).then(
                (data, error) => {
                    if(error) {
                        console.log(error);
                    } else {
                        // if no error, load data
                        countyGeoData = topojson.feature(data, data.objects.counties);
                        drawMap()

                    }
                }
            )
        }
    }
)

HTML代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>OSU Green Book SVG Demo</title>
        <link rel="stylesheet" href="timeseriesmap.css" />
        <script src="https://d3js.org/d3.v7.min.js"></script>
        <script src="https://d3js.org/topojson.v2.min.js"></script>
        <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js"></script> -->
        <style>
            /* Nothing here so far */
        </style>
    </head>
    <body>
        <main class="wrapper">
            <div class="container">
                <div class="sidebar">
                    <div class="title">
                        <h1 class="siderbar-title">The Green Book</h1>
                        <p class="sidebar-text">Body Text</p>
                    </div>
                    <div class="sliderContainer">
                        <div id="slider"></div>
                        <div class="year start-year">1938</div>
                        <div class="year end-year">1963</div>
                        <div class="zoom-button"></div>
                    </div>
                    <div class="content"></div>
                </div>
                <div class="map-container">
                    <div id="map-tooltip"></div>
                    <div class="map-key"></div>
                    <svg id="map"></svg>
                </div>
            </div>
        </main>
        <script defer src="timeseriesmap.js" type="text/javascript"></script>
    </body>
</html>
解决方案

报错核心是county变量为undefined,导致无法访问yearninteenthirtyeight字段,修正以下三点即可解决:

  1. 修正find回调逻辑:find的回调需要返回布尔值判断匹配,原代码仅在匹配时返回item,不匹配时无返回值,导致find无法正确识别匹配项。
  2. 统一FIPS编码类型:地理数据中的d.id是数字类型,自定义JSON中的fips可能是字符串类型,直接用===全等比较会匹配失败。
  3. 添加兜底逻辑:处理部分县在自定义数据中无对应记录的情况,避免undefined访问属性报错。

修改后的关键代码片段

.attr("fill", (d, i) => {
    let currentID = d.id;
    // 修正find回调,返回布尔值并统一类型比较
    let county = gbCountsData.find((item) => {
        return Number(item.fips) === currentID;
    });
    
    // 兜底:无对应数据时返回默认灰色
    if (!county) {
        return "#ccc";
    }
    return colorScale(county.yearninteenthirtyeight);
})

额外优化建议

  • 提前转换fips类型,避免重复计算:
    gbCountsData = data.map(item => ({
        ...item,
        fips: Number(item.fips)
    }));
    
  • 改用Map存储数据,查询效率远高于find:
    // 加载数据后创建Map
    const countyMap = new Map(gbCountsData.map(item => [item.fips, item]));
    
    // 回调中查询
    let county = countyMap.get(currentID.toString());
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:12:32