D3.js - 地理图形
D3.js - 使用地理数据
Section titled “D3.js - 使用地理数据”D3.js 提供了强大的工具用于可视化地理数据,常用于显示人口密度、天气模式或选举结果等信息的地图。D3 中用于地理空间数据的关键模块包括用于投影和路径生成的 d3-geo,以及常用于处理 TopoJSON 数据的 topojson-client。
D3 地理功能的核心组件是:
- GeoJSON/TopoJSON: 编码地理数据结构的标准格式。
- 投影 (
d3-geo): 将球面坐标(经度、纬度)转换为适用于屏幕显示的二维笛卡尔坐标系的函数。 - 路径生成器 (
d3-geo): 接受 GeoJSON 几何数据和投影,用于生成 SVG 路径数据(即<path>元素的d属性)或渲染到 Canvas 的函数。
D3 地理路径生成器
Section titled “D3 地理路径生成器”地理路径生成器,使用 d3.geoPath() 创建,用于将 GeoJSON 特征转换为 SVG 路径字符串或将其渲染到 HTML5 Canvas 上。它需要一个投影来执行坐标转换。
// 1. 创建一个投影 (例如,Mercator)const projection = d3.geoMercator() .scale(100) // 示例缩放比例 .translate([width / 2, height / 2]); // 地图居中
// 2. 创建一个地理路径生成器并将其关联到投影const pathGenerator = d3.geoPath() .projection(projection);
// 3. 将路径生成器与 GeoJSON 数据一起使用svg.selectAll("path") .data(geoJsonFeatures) // 一个 GeoJSON feature 对象的数组 .enter() .append("path") .attr("d", pathGenerator); // pathGenerator(d) 返回 SVG 路径字符串例如,要从一个名为 statesGeoJson 的 GeoJSON FeatureCollection 中绘制某个国家的州/省份界线:
svg.append("g") .selectAll("path") .data(statesGeoJson.features) .join("path") .attr("d", pathGenerator) .attr("fill", "steelblue") .attr("stroke", "white");投影将球面多边形几何数据(经度、纬度)转换为平面多边形几何数据(x, y 坐标)。D3 提供了各种各样的投影类型,每种在面积、形状、距离或方向的变形方面具有不同的特性。
- 方位角投影 (Azimuthal): 将球面直接投影到平面上(例如,
d3.geoOrthographic()、d3.geoStereographic())。 - 圆锥投影 (Conic): 将球面投影到圆锥上,然后展开圆锥(例如,
d3.geoAlbers()、d3.geoConicEqualArea())。 - 圆柱投影 (Cylindrical): 将球面投影到圆柱上,然后展开圆柱(例如,
d3.geoMercator()、d3.geoEquirectangular())。 - 组合投影 (Composite): 组合多个投影(例如,用于美国本土、阿拉斯加和夏威夷的
d3.geoAlbersUsa())。
要创建一个新的投影,请调用特定的投影函数:
const projection = d3.geoMercator(); // 创建一个 Mercator 投影
// 常用的配置方法:projection .scale(number) // 设置投影的缩放因子 .translate([x, y]) // 设置投影的平移偏移量(地图在像素空间中的中心) .center([lon, lat]) // 设置投影的中心点(经度、纬度) .rotate([lambda, phi, gamma]) // 设置投影的三轴旋转一些流行的投影:
d3.geoOrthographic(): 显示一个半球,如同从太空俯瞰。d3.geoGnomonic(): 将大圆投影为直线。d3.geoEquirectangular(): 一种简单的圆柱投影,常用于栅格数据。d3.geoMercator(): 常用于网络地图;局部保持角度不变,但在高纬度地区面积变形严重。d3.geoAlbersUsa(): 一种专门用于美国的组合投影。
实操示例:从 TopoJSON 绘制地图
Section titled “实操示例:从 TopoJSON 绘制地图”我们来创建一个国家(例如印度)的地图,使用 TopoJSON 数据。TopoJSON 是 GeoJSON 的一个扩展,它编码了拓扑结构,通常可以减小文件大小。
步骤 1: 包含 D3.js 和 TopoJSON 客户端库。您需要一个 TopoJSON 文件(例如,india-states.topojson)。
<!-- In your HTML --><script src="https://d3js.org/d3.v7.min.js"></script><script src="https://unpkg.com/topojson-client@3"></script> <!-- topojson-client library -->步骤 2: 定义 SVG 尺寸和投影。
const width = 600;const height = 500;
const projection = d3.geoMercator() .center([82, 22]) // 印度的大致中心 .scale(800) // 调整比例以适应 .translate([width / 2, height / 2]);
const pathGenerator = d3.geoPath().projection(projection);步骤 3: 创建 SVG 容器。
const svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .style("border", "1px solid black");步骤 4: 加载 TopoJSON 数据并渲染地图。我们使用 d3.json(),它返回一个 Promise 对象。
// Assume 'india-states.topojson' is available at this pathd3.json("india-states.topojson").then(function(topology) { // Convert TopoJSON to GeoJSON features // 'states' is the name of the object in your TopoJSON file that contains geometries const states = topojson.feature(topology, topology.objects.states);
svg.append("g") .selectAll("path") .data(states.features) .join("path") .attr("d", pathGenerator) .attr("fill", (d) => { // Example: Color Tamil Nadu (TN) differently if ID is available if (d.id === "TN") return "red"; return "#ccc"; }) .attr("stroke", "#333") .attr("stroke-width", 0.5);
}).catch(function(error) { console.error("Error loading or processing TopoJSON:", error);});步骤 5: (可选)添加 CSS 样式。
/* CSS (可选) */path { /* 路径的默认样式,除非被 .attr 覆盖 */}
path:hover { fill: orange; /* 示例悬停效果 */}关于 TopoJSON 数据 (india-states.topojson) 的说明:这个文件包含地理数据。topology.objects.states 部分指的是 TopoJSON 文件中一个特定的命名对象。该文件结构的一个高度精简的示例:
{ "type": "Topology", "transform": { /* scale and translate info */ }, "objects": { "states": { // This key 'states' is used in topojson.feature "type": "GeometryCollection", "geometries": [ { "type": "Polygon", "arcs": [[...]], "id": "AP", "properties": { "name": "Andhra Pradesh" } }, { "type": "MultiPolygon", "arcs": [[...]], "id": "TN", "properties": { "name": "Tamil Nadu" } }, // ... more state geometries ] } // ... other objects like 'districts' could be here }, "arcs": [ /* array of shared line segments */ ]}这个示例演示了加载地理数据,使用 topojson.feature 进行转换,并使用 D3 的路径生成器和投影进行渲染。具体的属性(d.id、d.properties.name)取决于您使用的 GeoJSON/TopoJSON 文件。