完美地图:使用 D3.js 制作精美的 Web 地图
已发表: 2022-03-11Data Driven Documents,或 D3.js,是“一个基于数据操作文档的 JavaScript 库”。 或者更简单地说,D3.js 是一个数据可视化库。 它是由 Mike Bostock 开发的,旨在弥合静态数据显示与交互式和动画数据可视化之间的差距。
D3 是一个功能强大的库,具有大量用途。 在本教程中,我将讨论 D3 的一个特别引人注目的应用:地图制作。 我们将讨论构建有用且信息丰富的 web 地图的常见挑战,并展示在每种情况下,D3.js 如何为有能力的 JavaScript 开发人员提供使地图看起来和感觉漂亮所需的一切。
D3.js 是做什么用的?
D3.js 可以将任意数据绑定到文档对象模型 (DOM),然后通过使用 JavaScript、CSS、HTML 和 SVG,对由该数据驱动的文档进行转换。 结果可以是简单的 HTML 输出,也可以是具有动态行为(如动画、过渡和交互)的交互式 SVG 图表。 所有的数据转换和渲染都是在客户端的浏览器中完成的。
在最简单的情况下,D3.js 可用于操作 DOM。 这是一个简单的示例,其中 D3.js 用于将段落元素添加到空文档正文中,并带有“Hello World”文本:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>D3 Hello World</title> <script src="http://d3js.org/d3.v3.min.js"></script> </head> <body> <script type="text/javascript"> d3.select("body").append("p").text("Hello World"); </script> </body> </html>
然而,D3.js 的优势在于它的数据可视化能力。 例如,它可用于创建图表。 它可用于创建动画图表。 它甚至可以用于集成和动画不同的连接图表。
D3 用于 Web 地图和地理数据可视化
但是 D3.js 不仅可以用于 DOM 操作,也可以用于绘制图表。 D3.js 在处理地理信息方面非常强大。 操作和呈现地理数据可能非常棘手,但使用 D3.js 构建地图非常简单。
这是一个 D3.js 示例,它将根据以 JSON 兼容数据格式存储的数据绘制世界地图。 您只需要定义地图的大小和要使用的地理投影(稍后会详细介绍),定义一个 SVG 元素,将其附加到 DOM,并使用 JSON 加载地图数据。 地图样式是通过 CSS 完成的。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>D3 World Map</title> <style> path { stroke: white; stroke-width: 0.5px; fill: black; } </style> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="http://d3js.org/topojson.v0.min.js"></script> </head> <body> <script type="text/javascript"> var width = 900; var height = 600; var projection = d3.geo.mercator(); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var path = d3.geo.path() .projection(projection); var g = svg.append("g"); d3.json("world-110m2.json", function(error, topology) { g.selectAll("path") .data(topojson.object(topology, topology.objects.countries) .geometries) .enter() .append("path") .attr("d", path) }); </script> </body> </html>
D3 的地理数据
对于本 D3.js 教程,请记住,地图构建最适合 JSON 格式的数据,尤其是 GeoJSON 和 TopoJSON 规范。
GeoJSON 是“一种用于编码各种地理数据结构的格式”。 它旨在表示离散的几何对象,这些对象被分组为名称/值对的特征集合。

TopoJSON 是 GeoJSON 的扩展,它可以对拓扑进行编码,其中几何“从称为弧的共享线段拼接在一起”。 TopoJSON 通过存储地理特征之间的关系信息而不仅仅是空间信息来消除冗余。 因此,几何图形在几何图形共享特征的情况下更加紧凑和组合。 这导致典型的 TopoJSON 文件比其 GeoJSON 等效文件小 80%。
因此,例如,给定一张地图,其中几个国家相互接壤,边界的共享部分将在 GeoJSON 中存储两次,一次用于边界两侧的每个国家。 在 TopoJSON 中,它将只有一行。
地图库:谷歌地图和 Leaflet.js
今天,最流行的地图库是谷歌地图和传单。 它们旨在快速轻松地在网络上获取“滑地图”。 “Slippy maps”是一个术语,指的是现代 JavaScript 驱动的 web 地图,它允许在地图上进行缩放和平移。
Leaflet 是 Google 地图的绝佳替代品。 它是一个开源 JavaScript 库,旨在制作适合移动设备的交互式地图,并考虑到简单性、性能和可用性。 Leaflet 在利用互联网上可用的大量基于栅格的地图时处于最佳状态,并带来了使用平铺地图及其演示功能的简单性。
当与 D3.js 的数据操作功能结合使用时,Leaflet 可以非常成功地使用,并且可以将 D3.js 用于基于矢量的图形。 将它们结合在一起可以在两个库中发挥出最好的效果。
谷歌地图更难与 D3.js 结合,因为谷歌地图不是开源的。 可以同时使用 Google Maps 和 D3,但这主要限于在 Google Maps 背景地图上使用 D3.js 覆盖数据。 如果没有黑客攻击,更深层次的集成是不可能的。
投影 - 超越球形墨卡托
如何将 3 维球形地球的地图投影到 2 维表面上的问题是一个古老而复杂的问题。 为地图选择最佳投影是每个 web 地图的重要决定。
在我们上面的简单世界地图 D3.js 教程中,我们通过调用d3.geo.mercator()
来使用球形墨卡托投影坐标系。 此投影也称为 Web Mercator。 谷歌在推出谷歌地图时推广了这种投影。 后来,其他网络服务也采用了投影,即 OpenStreetMap、Bing Maps、Here Maps 和 MapQuest。 这使得 Spherical Mercator 成为在线滑图的非常流行的投影。
所有映射库都支持开箱即用的球形墨卡托投影。 如果您想使用其他投影,则需要使用例如 Proj4js 库,它可以进行从一个坐标系到另一个坐标系的任何转换。 对于 Leaflet,有一个 Proj4Leaflet 插件。 就谷歌地图而言,什么都没有。
D3.js 将制图投影提升到一个全新的水平,内置支持许多不同的地理投影。 D3.js 将地理投影建模为完整的几何变换,这意味着当直线投影到曲线时,D3.js 应用可配置的自适应重采样来细分线并消除投影伪影。 Extended Geographic Projections D3 插件使支持的投影数量超过 40 个。甚至可以使用d3.geo.projection
和d3.geo.projectionMutator
创建一个全新的自定义投影。
栅格地图
如前所述,D3.js 的主要优势之一是处理矢量数据。 要使用栅格数据,可以选择将 D3.js 与 Leaflet 结合使用。 但也有一个选项可以使用 d3.geo.tile 仅使用 D3.js 来创建滑动地图。 即使仅使用 D3.js,人们也可以使用栅格地图做出令人惊奇的事情。
即时矢量操作
经典制图的最大挑战之一是地图泛化。 您希望拥有尽可能详细的几何图形,但这些数据需要适应显示地图的比例。 数据分辨率太高会增加下载时间并减慢渲染速度,而分辨率太低会破坏细节和拓扑关系。 使用矢量数据的易滑地图可能会遇到地图泛化的大问题。
一种选择是预先进行地图泛化:拥有不同分辨率的不同数据集,然后针对当前选择的比例显示适当的数据集。 但这会增加数据集,使数据维护复杂化,并且容易出错。 然而,大多数映射库仅限于此选项。
更好的解决方案是动态进行地图泛化。 D3.js 又来了,它具有强大的数据处理功能。 D3.js 允许在浏览器中进行行简化。
我想要更多!
D3.js 不易掌握,学习曲线陡峭。 需要熟悉很多技术,即 JavaScript 对象、jQuery 链式语法、SVG 和 CSS,当然还有 D3 的 API。 最重要的是,需要有一点设计技巧才能最终创造出漂亮的图形。 幸运的是,D3.js 有一个很大的社区,有很多资源可供人们挖掘。 这些教程是学习 D3 的一个很好的起点。
如果您喜欢通过查看示例来学习,Mike Bostock 在他的网页上分享了 600 多个 D3.js 示例。 所有 D3.js 示例都有用于版本控制的 git 存储库,并且是可分叉、可克隆和可注释的。
如果您使用 CartoDB,您会很高兴听到 CartoDB 让 D3 地图变得轻而易举。
最后,为了一点奖励,这是我最喜欢的例子之一,展示了 D3 的惊人能力:
- earth,一个使用 D3.js 制作的全球动画 3D 风图。 Earth 是全球天气状况的可视化,基于国家环境预测中心、NOAA / 国家气象局的超级计算机做出的天气预报并转换为 JSON。 您可以自定义显示的数据,例如风速读数的高度、更改叠加数据,甚至更改地球投影。