「Noah Veltman的午餐会」制作在线地图

分享给朋友:

[zilla_alert]在BBC工作期间,Noah Veltman 为编辑人员和设计师们组织了一系列午餐小会。这些小型讲座的内容不是关于如何写代码或者完成某个具体项目,而是让这些非工程人员了解在新闻实践中经常会遇到的技术话题,让技术问题不再那么高深莫测。当非工程人员对基础的技术有所了解后,“这个项目要花多长时间?”、“我们如何做出这样的东西?”、“我们要如何妥协才能在技术上实现它?”如此这般的问题就会被有效率的双向对话所替代。

出于这样的目标,这个系列中将不太涉及真正的写代码的教学。但对那些想好好钻研开发的人来说,这个系列将提供非常值得尝试的努力方向。这些都是真实发生在午餐会上的讨论,所以也许变成文字后少了一些临场感,但无论是对于程序员、记者还是设计师来说,这些都仍然是很有帮助的、值得学习的材料。

Noah Veltman现任纽约WNYC电台数据新闻团队的开发人员,擅长交互图表、地图和基于数据的新闻应用开发。此前他曾获得Knight-Mozilla开放新闻奖学金并在伦敦BBC NEWS工作。数据新闻网将陆续推出Noah Veltman午餐会的其他资源。

【Noah Veltman的午餐会】系列由数据新闻网独家授权编译,更多该系列文章:
【Noah Veltman的午餐会】Excel vs. Database
【Noah Veltman的午餐会】从网页抓取信息[/zilla_alert]

 

所以说你想要制作一张地图……

你确定吗?

仅仅因为有些东西能够用地图来表现,并不意味着就应该这样做,相关的故事可能和地图毫无关系。地图是有偏见的,可能具有误导性。它也许会强调土地的面积从而使人口密度的信息含混不清,或者说以一种地理的方式来展示从而忽略了所蕴含的人口统计学意义。所以在你着手制作地图之前,确保那是你真正想要的。

想要了解关于这个问题更详细的看法,可以阅读《When Maps Shouldn’t Be Maps》

 

地图是由什么组成的

地图通常包含地理数据(geographic data,在这里简称geodata)和一个可以可视化这些数据的系统

 

第一部分:地理数据

经度和纬度(Latitude and Longitude

你所遇到的大多数地理数据,都是基于地表的经纬度坐标(绘制火星地图并不在我们这篇入门级文章探讨的范围内)。

 

纬度的范围为-90°(南极)到90°(北极),0°为赤道。

经度的范围为-180°(由本初子午线向西围绕半个地球)到180°(由本初子午线向东围绕半个地球),0°为本初子午线。是的,这意味着-180°和180°是同一条经线。

11

如果你是一位旧时期的船长,你会发现经纬度是以“度、分、秒”的形式书写的,就像这样:

37°46’42″N, 122°23’22″W

电脑不是老船长,所以用小数表示会更加简便:

37.77833, -122.38944

 

一对经纬度的数据在英文中通常被称作“lat/lng”或者“lat/lon”。本文使用“lat/lngs”作为简写。

 

想要迅速地知道一对经纬度在地球上的位置?直接把它当作一个地址,在Google Maps里输入它。

 

*有些地图软件需要你给定的经纬度数组是以纬度打头,有些又要求以经度打头。所以在使用前你需要查看说明文件,看属于哪一种情况(或者你和我一样懒,两种都试一下就知道了)

 

*精确度很重要,所以要小心经纬度的取整。在赤道,一度经度覆盖的范围大约有69英里(约合111.044公里,译者注)!

 

地图几何学

几乎任何地理要素都能用一系列经纬度点来表达,它们像原子一样充当地图的基本构建模块。

 

一个位置(比如说,地图上的一个点)是一个单一的经纬度点:

37.77833, -122.38944

12

一条直线(比如说,地图上的一条街道)是一对经纬度点,一个是头一个是尾。

13

一条锯齿形的线,有时我们称之为“折线”,是一系列有序的直线的组合,也可以理解为是一系列有序的经纬度点:

7.77833,-122.38944 to 34.07361,-118.24

32.7073,-117.1566 to 33.445,-112.067

34.07361,-118.24 to 32.7073,-117.1566

14

一个封闭的区域(比如说地图上的一个国家),其实就相当于一种特殊的头尾相连的折线,它们被称为“多边形”:

37.77833,-122.38944 to 34.07361,-118.24

34.07361,-118.24 to 32.7073,-117.1566

32.7073,-117.1566 to 33.445,-112.067

33.445,-112.067 to 37.77833,-122.38944

15

总之:你能找到的几乎所有地理数据,无论它代表着世界上所有的国家,一系列周边的邮局,还是一组驾驶的路线,其本质上都是一群经纬度点。

 

地图的要素(features

大多数常见的地理数据格式是从要素上考虑的。要素可以是任何东西:一座城市,一条街,一个交通灯,一幢房子,一片湖,或者任何存在于一个固定的实际位置的物体。要素拥有几何结构(geometry)和属性(properties)。

要素的几何结构由任何前文所列举的几何元素(点,线,多边形,译者注)的组合构成。世界国家的地理数据由大约200个要素构成。*每一个要素都包括一系列的点,这些点一步步画出构成国家边界的折线,再回到起点,形成一个多边形。但是等等,你知道,并不是所有的国家都是一个单一的形状。如果是岛屿怎么办呢?没问题。只要将不相连的大陆作为额外的多边形添加进去就可以了。通过复杂的方式联合相对简单的几何元素,你可以呈现任何东西。

我们假设你制作了夏威夷群岛的地图,每一座岛屿都以一个多边形的形式呈现。那么它是七个要素还是一个要素呢?*这取决于我们制作的是什么种类的地图。如果以国家为单位分析某问题,我们只关注这些岛屿的整体意义,他们最终也将作为一个整体。因此它们可能更应当被看作一个拥有七个几何图形的地图要素。

如果是另一种情况,我们要制作一张夏威夷各岛屿野生生物的地图,我们需要它们作为七个独立的要素。也有一种叫做“要素集合”的东西,你可以出于某种目的将不同的要素归为一组。但我们现在先不用担心这个。

要素的属性是指其他所有会对你的地图产生影响的东西。例如“世界上所有的国家”这个地理数据,你需要国家的名字,但你可能同时需要比如出生率,人口,最大出口量,或者其他会被包含在地图内的信息。

*当你开始制作地图的时候,你可能会得到的教训之一是,那些你认为有简单答案的问题,例如“怎样才算是一个国家”“夏威夷有多少座岛屿”,变得有一些复杂了。

 

地理数据的格式

所以我们知道了地理数据就是一系列的要素,要素就是一系列的几何碎片,而每一个几何碎片就是一系列的经纬度坐标,于是乎所有的一切看起来就像是这个样子:

Feature #1:

geometry:

polygon #1: [list of lat/lngs]

polygon #2: [list of lat/lngs] (for Easter Island)

properties:

name: Chile

capital: Santiago

Feature #2:

geometry:

polygon #1: [list of lat/lngs]

polygon #2: [list of lat/lngs]

properties:

name: Argentina

capital: Buenos Aires

那么我们只需要一大堆经纬度点,然后就万事大吉了,是吗?当然不是。在真实的世界里,这些数据必须要以某种电脑所喜欢的、一致的形式存在。理想的情况是,这种格式人类也可以阅读。但咱们还是别这样奢求了。

 

既然你知道了地理数据的结构,你会发现,大多数常见的格式本质上是十分相似的。你可能会遇到的四大主流格式有:

 1. 图形文件(shapefiles

这是详细的地图数据最常见的格式。一个“图形文件”事实上是一系列文件:

l  .shp——所有要素的几何图形

l  .shx——帮助文件,有关图形顺序的信息存储于此

l  .dbf——以电子表格的形式存储着每一个要素的属性

l  其他可选择性的文件,存储着例如“项目描述与风格”(只有上述的三种文件是必须的)

 

如果在文本编辑器里面打开一个图形文件,会出现乱码,但如果用桌面端的地图软件(也叫做“GIS软件”或者“地理空间软件(geospatial software)”)打开,就可以很好地运行。图形文件非常适合用来对地理数据进行大量的细节操控和检查。但如果要制作网络地图,它们自己本身的格式是挺不合适的,但幸好通常都能被很轻易地转换为其它的格式。

 

2.GeoJSON

这是一种特别门类的JSON(JavaScript Object Notation,一种基于JavaScript语言的轻量级数据交换格式),适用于制作网络地图。并且,如果你在文本编辑器里面打开文件,它也是可读的。我们以科罗拉多州为例,因为它是长方形的,比较简单明了。

{
“type”: “Feature”,
“geometry”: {
“type”: “Polygon”,
“coordinates”: [
[
[-102.04,36.99],
[-102.04,40.99],
[-109.05,40.99],
[-109.05,36.99],
[-102.04,36.99]
]
]
},
“properties”: {
“name”: “Colorado”
“capital”: “Denver”
}
}

这段代码的意思是:画一个多边形,以[-102.04,36.99] 为起点,画一条线到下一个点[-102.04,40.99] ,然后重复这个过程直到列表的末尾。

请注意,最后一个点和第一个点是同一个点,以结束循环——大多数软件不要求提供这个额外的点,而是自己停止循环。

 

3.KMLKeyhole Markup Language,标记语言)

这是XML(Extensive Markup Language,可扩展标示语言)语言的一个特殊门类,深受Google Map,Google Earth以及Google Fusion Tables的喜爱。基本的代码组成和GeoJSON十分类似,只不过语句被包含在XML标签内而非花括号内。KML支持很多额外的附属项目,比如用于在Google Earth中呈现视频的摄影机定位和确定高度。它可以很好地插入Google的产品,但通常都需要被转换成为某种其他的东西,以便于制作其他的网络地图。所以科罗拉多州在KML里是什么样子的呢?

XML标签很容易令人产生疑惑,但是请注意,它的实质和GeoJSON很类似。它们都是一系列有序的点,用许多括号来装饰。

<Polygon id=”Colorado”>
<altitudeMode>clampToGround</altitudeMode>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-102.04,36.99
-102.04,40.99
-109.05,40.99
-109.05,36.99
-102.04,36.99
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>

 

4.TopoJSONGeoJSON的扩展,增加了拓扑逻辑的编码)

TopoJSON是最近的新宠。它拥有GeoJSON那样的基本地理数据格式,又取其精华去其糟粕,专注于地图中我们通常关心的部分:边界和连接(即拓扑)。具体的细节超出了这篇文章的范围,但你可以点击这里阅读有关TopoJSON的魔法。

 

要记住:不同的软件接受不同文件格式的地理数据,但是在最终人们所说的都是经纬度。不同的文件格式只是一种语言的不同方言。

 

我不是一个制图师,从哪里可以找到可用的地理数据?

有许多很棒的在线地理数据源。这里是一些有用的数据源:

 

Natural Earth

提供全地球一些不同数据集的图形文件下载:文化的(国家边界,州/省边界,道路,铁路,城市,机场,公园等)和实体的(海岸线,岛屿,河流,湖泊,冰川等)

US Census Bureau

全美国的详细图形文件或者KML文件

Geocommons

种类繁多的用户贡献地理数据,可以很方便地搜索,浏览或者预览。数据的可信度则良莠不齐

Wikimedia Commons

海量SVG格式详细地图,在网络上使用与修正很便捷(参看下文的“SVG/Canvas地图”)

OpenStreetMap

广为人知的数据库,覆盖全球的陆地,国家边界,道路和地标。它提供一种特殊的XML格式,必须经过转换才能被大多数软件所使用。因为它覆盖全球,并且道路和风景名胜的覆盖率较高,所以它通常被用来产生一套全球性的地图瓦片(参看下文的“可滑动地图”)

Google

如果你没有所需的地图数据,那就向四周看看!当你望过去时,你会惊讶于那里有多么丰富的数据

Ogr2ogr Converter

并不是一个数据源,但是是一个便捷的格式转换器,可以将图形文件和GeoJSON文件互换

Desktop GIS Software

你需要掌握桌面GIS软件的用法,特别是要处理的图形文件的时候。Quantum GIS既免费又好用。Arc GIS也很强大,但价格非常昂贵。这些本身都不是数据源,却是一种在制图之前将不完美的数据整理调教成形的重要方法。

 

提醒:对所有找到的地理数据持怀疑的态度,特别是在它很复杂或者需要结合不同信息源数据的情况下。地理数据在良莠不齐的网络信息里并不算一个特例。怪异的图形文件,错误标注的地点,缺失的拼图碎片,这些都不少见。

 

第二部分:将地理数据转变成网络地图

在这些数据上下那么多苦功夫,就是为了做一个很酷的地图不是吗?所以让我们忘了那些花括号和几何学课程,着手做起来吧。一般来说,要将数据在网上以地图呈现,有三种方式供你选择。在我们谈到它们之前,确保问自己下列问题:

 

所有的地图都必须是交互的吗?

仅仅因为你可以将地图做成动态交互的形式,并不意味着就应该这样做。新闻里一些最优秀的地图都只是一张图片。图像在网上显示效果很好,因为几乎所有需求都能得到支持。图片并不是其他方式的替代品,因为为了制作一张图片,你需要先用其他工具制作一张地图:桌面GIS软件,Adobe Illustrator,或者下面所说的三个选项之一。一旦做出了想要的呈现效果,你可以要么截图,要么导出图片。就算现在,避免不必要的交互性和复杂性,选用简单平实的图片,会减少很多令人头疼的工序。

 

选择一:可滑动地图(Slippy Maps

16

无论你是否意识到,你已经用过很多可滑动地图了。Google Maps 就是一个可滑动地图,Yahoo! Maps 也是。MapQuest仍旧存在吗?如果存在,那也可能是一个可滑动地图。我使用“可滑动”这个词,指的是地图的背景层可自由滑动,允许你平移或者缩放以达到理想的状态。这种可滑动地图蕴含的魔法,本质上是背景的一系列“瓦片”。它们只是普通的图片,所以你也可以称之为“拼接地图”。

在每一个缩放的层级,整个地球都被一个巨大的网格所分割。无论你处在地图上的何处,他都会加载你正在看的那一个方格,并且开始加载周围的方格以防你四处移动。当你移动地图,它又会开始加载你需要的新的内容。你也可以在瓦片的顶层添加其他图层和可以点击的物体,但那些瓦片是可滑动地图的最基本部件。

17

可滑动地图很棒,因为:

  1. 它们在浏览器上使用方便,且对带宽没有特殊要求。你只需要加载你要看的那部分区域。并且,可滑动地图是基于图像的,所有的主流浏览器和设备都支持。
  2. 人们已经习惯了它们。由于Google Map的流行,每个人都曾多次练习使用可滑动地图。
  3. 它们能够很轻松的根据屏幕大小进行调节。你只需要缩小地图框架,而下面的地图瓦片是不会变的。
  4. 它们能够优雅地支持大多数主要的地图功能,比如说缩放,平移,加标注。它记录了各种纷乱的细节,所以你可以专注于地理信息。

 

可滑动地图也有缺点:

  1. 生成自己的地图瓦片将是一件复杂的事情,这要求数据,式样,还有一些技术能力
  2. 即便可以沿用老地图的瓦片,或者借用其他人的瓦片,你会牺牲掉良好的视觉控制
  3. 基于图像的瓦片并不太适合动态效果
  4. 经常会受限于标准网络墨卡托地图投影以及缩放行为

 

按经验法则来讲,可滑动地图是一个好的选择,只要:

–  浏览器兼容性及性能十分优秀

–  你需要在不同缩放程度下展示一个很大的可浏览区域

–  并不需要对所有事情进行精确的视觉操控

–  并不是所有的地图组成部分需要是动态的或者交互的

 

怎样才能制作一个可滑动地图?

为了用地理数据制作一张可滑动地图,事实上你要做两张地图:

  1. 背景瓦片——你需要提供给软件一套数据,关于哪里是陆地,哪里是道路,哪里是风景名胜,等等,这样软件就可以基于这些数据生成图片。如果对现成的地图瓦片满意,你可以略过这一步(见下文)
  2. 其他内容——一旦有了地图瓦片,你就可以用地理数据在顶层添砖加瓦,例如标记或者强调的线条。

 

Leaflet 是制作可滑动地图最好的资源之一。这个程序库会完成大多数脏活累活,从而让你能够更加专注于定制地图。你需要些一点点JavaScript基础,但可能比你想象得要少多了。

 

这里我们介绍怎样在Leaflet里面画出科罗拉多州:

map.addLayer(new L.polygon([

[36.99,-102.04],

[40.99,-102.04],

[40.99,-109.05],

[36.99,-109.05]

]));

18

Leaflet也使用GeoJSON语言,所以如果我们有一个包含这些坐标的GeoJSON文件,是可以直接打开的:

L.geoJson(states).addTo(map);

在Leaflet里你可以使用任何地图瓦片,包括Google Maps。

 

瓦片

你可以用TileMill生成自己的背景瓦片

这里有一个十分详细的教程,关于怎样用TileMill生成自己的瓦片

你可以用CloudMade基于OpenStreetMap数据创建自定义风格的瓦片

也可以从Stamen Design那里借用好看的瓦片

或者使用Google Maps 作为你的基础瓦片。

MapBox上有一个详细的指导,关于可滑动地图基础技术的具体细节。

 

选择二:JavaScript+SVG/Canvas

19

画地图的另一个选择是从另一个网页抓取地图,这一般是用SVG(可伸缩向量图形,Scalable Vector Graphics 译者注)或者HTML5 <canvas>元素来实现。这两者都是在网页上创建绘图空间,然后基于一套指令绘制大量线条与图形的的方法。不像地图那样使用经纬度点,这两种方法用的是像素。左上角的点是“0,0”,其他任何像素都是(x,y)。x代表这个点距离左上角的点右方多少个像素,y代表距离下方多少个像素。

20

SVG看起来和HTML类似,因为它本质上就是HTML。

<svg width=”400″ height=”200″>

[Your drawing instructions go here]

</svg>

它允许你绘制基本的图形,比如线条,圆圈,长方形。也能做一些进阶的事情,比如渐变和动画。当处理地图的时候,你将会面对很多路径元素,这是标准SVG画线的方式,也可以扩展到复杂的多边形。它们可以是直线,折线,曲线,秋葵线,油炸线,炖线,任何你能说出的线。一条路径从一大堆指令(即数据串)中找到属于自己的指令,用于指导它应该画什么。

<path d=”M200,0 L200,200 Z” /> (Start at 200,0, draw a line to 200,200, and then stop)

这样的句法或许会有一点令人头大,但它与用经纬度点生成多边形的原理并无二致。它只是用了不同的缩写:M代表从哪儿开始,L代表下一条线画到哪儿,Z代表停止。你可以使用完全相同的体系去绘制像国家这样的图形,只是需要多一些的点。你可以这样画阿鲁巴:

<path id=”Aruba” d=”M493.4952430197009,554.3097009349817 L493.6271899111516,554.5053144486982 L493.7591368026024,554.5053144486982 L493.7591368026024,554.6357015002002 L493.8910836940532,554.7660710469861 L493.8910836940532,554.8964231416435 L493.7591368026024,554.8964231416435 L493.6271899111516,554.8964231416435 L493.6271899111516,554.8312492725454 L493.7591368026024,554.8312492725454 L493.7591368026024,554.7660710469861 L493.6271899111516,554.7008884583952 L493.36329612825017,554.5053144486982 L493.23134923679936,554.5053144486982 L493.23134923679936,554.4401143422353 L493.23134923679936,554.3749098398575 L493.23134923679936,554.3097009349817 L493.23134923679936,554.2444876210226 L493.23134923679936,554.1792698913926 L493.23134923679936,554.1140477395024 L493.36329612825017,554.2444876210226 Z” />

 

你会注意到这些数字远超出了经纬度应有的范围,那是因为它们并不是经纬度点。它们是特定大小的绘图空间里的像素值。要从经纬度点转换到像素,你需要使用地图投影(map projection),一种将经纬度点转换到二维绘图的方法。

在制作可滑动地图的时候,你通常会自动采用Web墨卡托投影,但是其实还有许多其他的投影方法。在制作SVG/Canvas地图的时候,你就需要从中选择一种。这有一点超出这篇入门读物的范围了,但是你可以阅读有关嵌入式d3地图投影的内容.

 

SVG/Canvas 地图很棒,因为:

  1. 你拥有完全的视觉控制。你可以以一块空白的画布开始,决定有关它外形的一切
  2. 它们能以一种新颖且令人兴奋地方式,达成交互与动态的效果。与其他元素一样,每一块地图都是页面上的一个元素,所以你可以用CSS和JavaScript轻松地操纵与设计。
  3. 你并不需要真实的地理数据来做一张地图。如果你已经有了一个SVG(Scalable Vector Graphics,可伸缩向量图形,译者注),比如说维基世界媒体地图,你可以跳过所有复杂的经纬度点步骤直接用它

 

SVG/Canvas 地图也不那么好,因为:

  1. 它们存在浏览器兼容问题,IE8并不支持它们。(你可以为IE7和IE8添加特定的程序库以达到支持)
  2. 你的数据是经纬度点的形式,而输出是以像素的形式,所以画图之前你需要运用地图投影技术来转换数据
  3. 当图形趋于复杂时,性能能为一个问题
  4. 通常要求使用者有较高的JavaScript水平
  5. 使用者并不一定知道做什么。只要地图偏离了使用者原先的习惯,你就不得不很快地教会那些缺乏耐心的使用者这独特新颖的地图是怎样运作的。

 

我怎样才能做出一个地图呢?

目前为止,动态绘制地图最流行的方法是利用d3,一个极其出色但有时候又会让你费解的基于JavaScript的程序库。它可以做很多事情,地图只是冰山一角。

有许多d3地图的例子和教程,但如果你没有足够的JavaScript知识,那也没有用。

http://bost.ocks.org/mike/map/
http://www.schneidy.com/Tutorials/MapsTutorial.html
http://www.d3noob.org/2013/03/a-simple-d3js-map-explained.html

如果你不想过多的纠缠于JavaScript,Kartograph.js也是一个不错的选择。并且还有一个好处就是IE7和IE8都能支持。

 

选择三:让其他人做大部分工作

如果你已经准备好了地理数据,其实有很多服务等着你,能够帮你处理许多制图的工作,对输出的控制程度也有多种选择:

Google Maps

Google Earth

Google Fusion Tables

CartoDB

BatchGeo

本文译者:袁竞逐

 

 

作者简介

数据新闻网

数据新闻网以引介全球范围内最顶尖的数据新闻实践为初衷,以推动数据开放及媒体革新为宗旨,面向中国的新闻从业者、媒体管理者、新传教育者以及对传媒感兴趣的设计师、程序员,提供线上信息平台与线下交流机会。