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

使用D3.js从Overpass API生成的OSM XML绘制点时遇类型错误

解决D3.js加载OSM XML绘制圆形时的TypeError错误

问题描述

尝试用D3.js读取Overpass API生成的OSM XML文件,绘制对应node元素的圆形时,触发错误:
TypeError: null is not an object (evaluating 'node.getAttribute')
XML文件包含4个带经纬度的node元素,但无法正常渲染。

错误原因及修正步骤

  1. 缺少SVG容器
    原代码中d3.select("svg")找不到对应元素,返回null,后续获取宽高时直接报错。需要在HTML的<body>里添加指定宽高的SVG标签。

  2. 数据格式不兼容
    documentElement.getElementsByTagName("node")返回的是HTMLCollection对象,D3无法直接处理这类类数组结构,需要转换为普通数组。

  3. 错误的图形元素标签
    原代码append自定义的myCircles标签,SVG无法识别,应该使用标准的<circle>元素。

  4. 未进行地理投影转换
    XML中的经纬度是地理坐标,需要通过D3的投影方法转换为SVG画布的像素坐标,不能直接作为cx、cy属性值。

修正后的完整代码

HTML代码

<!DOCTYPE html>
<html>
<meta charset="utf-8">

<head>
    <script type="text/javascript" src="https://d3js.org/d3.v4.js"></script>
</head>

<body>
    <!-- 添加带宽高的SVG容器 -->
    <svg width="800" height="600"></svg>
    <script>
        var svg = d3.select("svg"),
            width = +svg.attr("width"),
            height = +svg.attr("height");

        var projection = d3.geoMercator()
            .scale(21000000) 
            .center([-122.29576905, 37.890256])
            .translate([width / 2, height / 2])  // 调整平移参数让图形居中

        d3.xml("entrance-exit.xml", function(error, xml) {
            // 将HTMLCollection转换为数组
            var nodesArray = Array.from(xml.documentElement.getElementsByTagName("node"));
            
            svg
                .selectAll("circle")
                .data(nodesArray)
                .enter()
                .append("circle")  // 使用标准circle元素
                .attr("cx", function(d) { 
                    // 投影转换:先转成[lon, lat]格式,再获取x坐标
                    return projection([d.getAttribute("lon"), d.getAttribute("lat")])[0]; 
                })
                .attr("cy", function(d) { 
                    return projection([d.getAttribute("lon"), d.getAttribute("lat")])[1]; 
                })
                .attr("r", 8)
                .style("fill", "blue")
                .attr("stroke", "black")
                .attr("stroke-width", 1)
                .attr("fill-opacity", 1);
        })
    </script>
</body>
</html>

XML文件(无需修改)

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API 0.7.59 e21c39fe">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base="2022-11-01T11:22:37Z"/>

  <bounds minlat="37.8885000" minlon="-122.2966000" maxlat="37.8906000" maxlon="-122.2945000"/>

  <node id="10054221950" lat="37.8899635" lon="-122.2960219">
    <tag k="entrance" v="yes"/>
  </node>
  <node id="10054221951" lat="37.8894885" lon="-122.2951210">
    <tag k="entrance" v="yes"/>
    <tag k="wheelchair" v="yes"/>
  </node>
  <node id="10091017732" lat="37.8894072" lon="-122.2952833">
    <tag k="entrance" v="yes"/>
    <tag k="ref" v="25"/>
  </node>
  <node id="10091017733" lat="37.8894276" lon="-122.2951869">
    <tag k="entrance" v="yes"/>
    <tag k="ref" v="26"/>
  </node>

</osm>

关键修正说明

  • 新增<svg width="800" height="600"></svg>作为绘图容器,确保D3能获取到有效的SVG元素
  • 使用Array.from()将HTMLCollection转为数组,让D3可以正常绑定数据
  • 替换append("myCircles")为append("circle"),使用SVG标准图形元素
  • 通过projection([lon, lat])将地理坐标转换为SVG画布的像素坐标,正确计算cx和cy值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:26:13