D3 Geo
在D3中除了常用的学术图表之外,还支持地图的数据展示,主要分为地理路径、地理投影
,D3支持少数的组件来显示和操作数据。一般地图数据会保存为JSON
格式,而D3常用的有GeoJson and TopoJSON
,其中GeoJson
主要描述地理信息的一种基本格式。而TopoJSON
则是由D3作者Mike Bostock制定的格式,他们都符合了JSON的规范。
D3支持少数的组建来显示和操作数据,这些组件会使用GeoJSON
格式,他也是JavaScript中标准的地理特征表示方法。而由Mike Bostock所制定的格式TopoJSON
主要是GeoJSON
的扩展格式,前者表示的更加紧密。
如果要将文件转换为GeoJSON
格式,需要通过使用GDAL``包中的 ogr2ogr
来进行转换,当让也有从 ogr2ogr
衍生出的 ogr2gui
但本文主要通过使用 ogr2ogr
来进行转换,通常 D3 Geo 常用 API 如下:
ID | DA | FA |
---|---|---|
d3.geo.mercator() | 莫卡托投影,是正轴与圆柱投影,由荷兰地图学家莫卡托(mercator)与1569年创立 | |
center(one[,two]) | 地图中心位置,通常one是经度、two是维度 |
|
d3.geo.path() | 创建一个新的地理路径生成器 | |
projection | 应用投影 | |
d3.set() | 创建集合 | |
.has() | 用于检测数据是否在集合中 |
数据的来源
DataV
DataV是阿里巴巴数据可视化团队,旨在让更多人看到数据可视化的魅力,本文主要使用 DATAV所提供的地理地图集(DATAV.GeoAtlas
),通过使用DATAV我们可以直接得到相应地图的 JSON数据,从而避免 使用 ogr2ogr
进行二次转换。
数据可以直接通过访问http://datav.aliyun.com/tools/atlas/#&lat=30.316551722910077&lng=102.21432656555675&zoom=3.5
得到,除此之外,我们也可以根据 DATAV 所提供的 API 直接进行绘制:
ID | DA |
---|---|
https://geo.datav.aliyun.com/areas_v2/bound/100000.json | JSON API |
https://geo.datav.aliyun.com/areas/bound/geojson?code=100000 | GeoJSON API |
https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json | JSON API (包含子域) |
https://geo.datav.aliyun.com/areas/bound/geojson?code=100000_full | GeoJSON API (包含子域) |
Natural Earth
Natural Earth 提供的部分 GeoJSON 存在中国地图部分不完整或存在缺陷等问题而 Github 上部分的 china.json / china.geojson 等数据可能存在通过使用 -where "ADM0_A3 ('CHN','TWN')" 进行拼合而成,因此,也可能存在中国地图中的钓鱼岛、赤尾屿、台湾岛、南海诸岛、藏南地区国界线、阿克赛钦地区国界线等错误。
因此我们强烈建议使用阿里巴巴DataV与高德开放平台所提供的在线数据提供平台: http://datav.aliyun.com/tools/atlas/#&lat=30.332329214580188&lng=106.72278672066881&zoom=3.5 内进行下载geojson或svg数据。本文虽然不采用 Natural Earth 数据,但提供使用以通过 ogr2ogr 转换的步骤和数据的简化操作。
如果我们不使用中国地图的话,可以通过Natural Earth
这个带有美国特色双标组织渠道来下载所有地理数据,他主要提供了三种尺寸供我们进行下载:
ID | FA | DA |
---|---|---|
大规模数据 | 1:10m,1:10,000,000,1英寸= 158英里,1厘米= 100公里 | 最详细且使用与制作国家和地区的放大地图 |
中等规模数据 | 1:50m,1:50,000,000,1英寸= 790英里,1厘米= 500公里 | 适用于制作国家和地区的缩小地图 |
小规模数据 | 1:110m,1:110,000,000,1’’= 1,736英里,1厘米= 1,100公里 | 小型的示意图或小型的定位器的地球仪 |
当下载的时候,他主要会分为Cultural、Physical、Raster
三个选项:
ID | DA | FA |
---|---|---|
Cultural | 包含具有文化性 的地理信息 |
具有国家和地区的边界划分地图、按照行政省划分地图、包含有飞机场、港口和地图等 |
Physical | 包含具有物理性 的地理信息 |
含有该国家的海岸线、陆地、海洋、河流、港口等 |
Raster | 包含栅格地图 |
GeoJSON 转换
我们通过在 Natural Earth
下载的 Admin 0 – Countries
1:110m 的地图数据,在此之前,我们需要安装GDAL
包下的ogr2ogr
程序,如果你是 Linux debian 系用户可以通过使用:
1 | sudo apt-get install gdal-bin |
当安装成功之后,使用ogr2ogr -version
来进行查询是否安装成功,当正确输出版本信息后。我们可以将刚刚下载到的ne_110m_admin_0_countries.zip
进行解压,解压后进入该目录执行:
1 | ogr2ogr -f "GeoJSON" china.geojson ne_110m_admin_0_countries.shp -overwrite -where "ADM0_A3 IN ('CHN')" |
也可使用 -where "ADM0_A3 IN ('CHN','USER')"
来提取多个国家数据,ISO 3166-1 alpha-3即“ADM0_A3”标准来通过三个拉丁字母表示国家名称,通常这三个字母就是该国家的代码,如CHN
就是中华人民共和国
的国家代码。
TopoJSON 转换
TopoJSON 是由 Mike Bostock 提供的一种 GeoJSON 扩展,通过拓扑后的扩展形式,主要使用点、弧
来表示图形。一般情况点、线地理实体分别通过坐标和弧索引表示
而多边形也通过弧索引来实现。
使用 TopoJSON 的特点在于其大小是 GeoJSON 大小的 80%
,原因在于边界线只记录一次(边界线接壤、共用),而地理坐标都使用整数
即 **共享边(ARCS)**。
因此 TopoJSON 通过明显的优点深受喜爱,除此之外,还可以通过使用 TopoJSON 内 共享边(ARCS) 的特性来完成一些较为舒服用户交互或特殊标注
。
TopoJSON 提供了解析 TopoJSON 格式的方法,为了保证 TopoJSON 的拓扑保留简化和过滤以及更小的文件、更快的渲染,因此 TopoJSON 还特地除了个简化步骤
。除此还分为客户端和服务器
,两者分别是将 GeoJSON 转换为 TopoJSON,以及将 TopoJSON 转换为 GeoJSON
:
ID | DA | FA | TO |
---|---|---|---|
服务器 | TopoJSON.Topology | 支持将 GeoJSON 转换为 TopoJSON | https://github.com/topojson/topojson-server/blob/master/README.md#topology |
Geo2topo | 将 GeoJSON 转换为 TopoJSON | https://github.com/topojson/topojson-server/blob/master/README.md#geo2topo | |
简化 | TopoJSON.presimplify | 准备用于简化的 TopoJSON | https://github.com/topojson/topojson-simplify/blob/master/README.md#presimplify |
TopoJSON.simplify | 删除坐标来简化 | https://github.com/topojson/topojson-simplify/blob/master/README.md#simplify | |
TopoJSON.quantile | 计算简化的阀值 | https://github.com/topojson/topojson-simplify/blob/master/README.md#quantile | |
TopoSimplify | 简化 TopoJSON 删除坐标 | https://github.com/topojson/topojson-simplify/blob/master/README.md#toposimplify | |
客户端 | topoJSON.feature | 将 TopoJSON 转换为 GeoJSON | https://github.com/topojson/topojson-client/blob/master/README.md#feature |
…… | https://github.com/topojson/topojson |
GeoJSON > topoJSON
通过使用 TopoJSON Server 所提供的 topojson.topology 可以通过将GeoJSON
转换为TopoJSON
文件,可以使用sudo npm install -g topojson-server
进行安装, tpology 自带了geo2topo
。
我们可以通过执行 geo2topo china.json -o china_topo.json
将 geoJSON 文件转换为 TopoJSON 格式文件 china_topo.json
当然你也可以通过使用其官方所提供的 <script src="https://unpkg.com/topojson-server@3"></script>
在浏览器中进行引入,这是由官方所提供的3.0.1
版本
TopoJSON > GeoJSON
可以使用 topoJSON.feature
来进行转换,feature 主要分为客户端和浏览器引入两种方法。通过使用cnmp install -g topojson-client
来进行全局安装,当然如果没有cnmp
也可以通过nmp install -g topojson-client
进行安装,但速度会比较慢。
如果通过浏览器引入我们可以通过使用 <script src="https://unpkg.com/topojson-client@3"></script>
来进行引入,这是由官方所提供的3.0.2
版本。
简单绘制
GeoJSON
GeoJSON 是一个用于描述地理空间信息
的数据格式,因此他的语法是符合JSON规范,只是和JSON不同之处在于对名称进行了规范
,名称须为字符串,而值可以是字符串、数字、布尔、对象、数组、NULL
等,通常他的外部对象格式是:
2015年,互联网工程任务组(IETF)与最初的的规范作者共同组成了
GeoJSON WG
,以标准化GeoJSON。RFC 7946 于2016年8月发布,他是GeoJSON格式的新规范,取代了2008年的GeoJSON 规范:
1 | { |
通常上述 code 主要分为Fature(特征)
以及geometry(几何体)
来表示出最外层的单独对象,在特征集合(FeatureCollection
)中,最外层的GenJSON
会包含很多的子对象,对于每一个GeoJSON
的每个type
属性值必须是下面之一:
ID | DA |
---|---|
Point | 点 |
MultiPoint | 多点 |
LineString | 线 |
MultiLineString | 多线 |
Polygon | 面 |
MultiPolygon | 多面 |
GeometryCollection | 几何体集合 |
Feature | 特征 |
FeatureCollection | 特征集合 |
1 | { |
绘制
由于我们使用的是DATAV
所提供的数据,因此我们你可以通过使用d3,geo.mercator()
进行投影,然后使用center()
来设置出地图的中心位置。select ad translate
分别设置缩放量和平移量,当定义好投影之后,通过使用d3.geo.path()
来进行使用投影进行绘制地图路径。
1 | var padding = { |
CSS
1 | .province { |
TopoJSON
TopoJSON 是由 Mike Bostock 提供的一种 GeoJSON 扩展,通过拓扑后的扩展形式,主要使用点、弧
来表示图形。一般情况点、线地理实体分别通过坐标和弧索引表示
而多边形也通过弧索引来实现。
使用 TopoJSON 的特点在于其大小是 GeoJSON 大小的 80%
,原因在于边界线只记录一次(边界线接壤、共用),而地理坐标都使用整数
即共享边(ARCS)。
因此 TopoJSON 通过明显的优点深受喜爱,除此之外,还可以通过使用 TopoJSON 内 共享边(ARCS) 的特性来完成一些较为舒服用户交互或特殊标注
。
TopoJSON 提供了解析 TopoJSON 格式的方法,为了保证 TopoJSON 的拓扑保留简化和过滤以及更小的文件、更快的渲染,因此 TopoJSON 还特地除了个简化步骤
。除此还分为客户端和服务器
,两者分别是将 GeoJSON 转换为 TopoJSON,以及将 TopoJSON 转换为 GeoJSON
:
ID | DA | FA |
---|---|---|
topojson.feature | 将 TopoJSON 转换为 GeoJSON,为返回指定的对象 GeoJSON | |
topojson.merge | 合并 Topojson 集合,并分配个目标对象 | |
topojson.mesh | 与 topojson.mesh 等效,但返回的是 TopoJSON,可以用于共享坐标 | |
topojson.neighbors | 计算出相邻数据 |
绘制
在下述的 code 中主要通过使用 geojson 格式转换为 topojson 格式,之后在通过使用topojson.feature
将此再次使用<script src="https://unpkg.com/topojson@3.0.2/dist/topojson.js"></script>
API 转换为 geojson 格式文件。因源文件是 topojson 所以转换后的数据自然是 geojson 文件的 80% 大小,这也是使用 topojson 的好处之一。
1 | var padding = { |
set and merge
通过 d3.set 创建集合,southeast 包含了各省名称之后通过使用 southeast.has() 来检查传入字符串是否在集合中,合并后保存并输出。 我们将 southeast 内设置为黑色,之后使用 datum()来绑定数据通过 svg.path 进行绘制。
使用 topojson.merge() 来进行合并,每一项保存一个省的几何信息,之后通过对象的 filter() 函数,只有在集合中的省份保存至 mergedPolygon 中。
1 | var padding = { |
mesh
topojson.mesh 主要提供了 网格花 TopoJSON 几何形状以形成多边形, 分别提取了内蒙古、黑龙江省的边界线,边界线最终存储在 boundary 中。
1 | var padding = { |
neighbors
通过使用 neighbors 来计算出相邻数据,并通过为没一个元素添加相邻省份的选择集,为每个选择时添加 behavior 事件,持续时间分别为 2000ms。
1 | var padding = { |