7.4. 使用GeoJSON

GeoJSON是一种广泛使用的数据格式,用于在web地图中显示矢量。它基于JavaScript对象表示法,这是一种使用JavaScript语法来表示数据结构的简单而极简的格式。在GeoJSON中,向量特性及其属性被表示为JavaScript对象,允许轻松解析几何体和字段。

与基于XML的结构(如KML)相比,GeoJSON的体积较小;但是,GeoJSON并不总是像KML那样包含样式信息。您必须在客户机上定义样式,在您的情况下,这意味着编写JavaScript代码或采用 Leaflet 的默认样式。这将在本课的下一节中介绍。

GeoJSON的简单性和加载速度使得它在自由/开源软件世界的开发人员中很受欢迎,甚至很流行。例如,在一个开玩笑的互联网民意调查中,地理信息系统从业者最近将“答案总是GeoJSON”作为最有可能定义“GeoHipster”的属性。

这是一块GeoJSON的样子。GeoJSON向量通常被捆绑到一个叫做FeatureCollection的单元中。下面的FeatureCollection只包含一个功能(蒙大拿州),但可以包含其他功能。下面的大部分GeoJSON包含定义状态大纲的顶点,但是您还应该注意一些属性,比如“fips”和“name”:

{"type":"FeatureCollection","features":[{"type":"Feature","id":"USA-MT","properties":{"fips":"30","name":"Montana"},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,49.000239],[-104.042057,47.861036],[-104.047534,45.944106],[-104.042057,44.996596],[-104.058488,44.996596],[-105.91517,45.002073],[-109.080842,45.002073],[-111.05254,45.002073],[-111.047063,44.476286],[-111.227803,44.580348],[-111.386634,44.75561],[-111.616665,44.547487],[-111.819312,44.509148],[-111.868605,44.563917],[-112.104113,44.520102],[-112.241036,44.569394],[-112.471068,44.481763],[-112.783254,44.48724],[-112.887315,44.394132],[-113.002331,44.448902],[-113.133778,44.772041],[-113.341901,44.782995],[-113.456917,44.865149],[-113.45144,45.056842],[-113.571933,45.128042],[-113.736241,45.330689],[-113.834826,45.522382],[-113.807441,45.604536],[-113.98818,45.703121],[-114.086765,45.593582],[-114.333228,45.456659],[-114.546828,45.560721],[-114.497536,45.670259],[-114.568736,45.774321],[-114.387997,45.88386],[-114.492059,46.037214],[-114.464674,46.272723],[-114.322274,46.645155],[-114.612552,46.639678],[-114.623506,46.705401],[-114.886399,46.809463],[-114.930214,46.919002],[-115.302646,47.187372],[-115.324554,47.258572],[-115.527201,47.302388],[-115.718894,47.42288],[-115.724371,47.696727],[-116.04751,47.976051],[-116.04751,49.000239],[-111.50165,48.994762],[-109.453274,49.000239],[-104.047534,49.000239]]]}}]}

在上面的GeoJSON中,注意几个JavaScript对象的使用。在最底层,有一个多边形对象。多边形对象包含在要素对象中。该功能是FeatureCollection对象的一部分。那个GeoJSON specification (最初于2008年发布,但在2016年被新规范取代)给出了这些对象的结构的精确细节。熟悉这些结构是很重要的,尽管你很少需要直接读或写它们。通常,您将使用为简化使用GeoJSON的经验而开发的便利类或转换程序。

您可以在您的主JavaScript代码文件中使用GeoJSON,但是,为了使您的事情看起来简单,在自己的单独文件中维护GeoJSON是最常见的。然后从代码中的适当位置引用此文件。有了 Leaflet 你必须定义GeoJSON as a JavaScript variable (seen here) 使用诸如

var <yourVariableName> = <yourGeoJSON>;

您可以将此文本保存在扩展名为.js的文件中。例如,我可以创建一个名为myfeatures.js的文件,其中包含如下内容:

var myGardenJson = {"type":"FeatureCollection","features":[{"type":"Feature","id":"USA-MT","properties":{"fips":"30","name":"Montana"},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,49.000239], . . . ]]}}]};

然后,在我的HTML页面的顶部,我需要放置对该文件的引用:

<script src="myfeatures.js"></script>

这允许我在JavaScript代码中引用变量myGardenJson。在 Leaflet 中创建一个GeoJSON层变得非常简单:

var geojsonLayer = L.geoJSON(myGardenJson);
geojsonLayer.addTo(map);

需要注意的是,L.geoJSON(…)期望geoJSON文件中的所有坐标都是WGS84坐标。这就是为什么本课和第8课中使用的所有GeoJSON文件都将使用EPSG:4326。如果您想直接使用使用不同投影的GeoJSON文件(因此不必首先将其重新投影到EPSG:4326),可以使用Proj4js Javascript库和Proj4Leaflet 扩展以支持未嵌入传单的坐标参考系。为此,首先必须在html文件的开头添加行以加载相应的Javascript库

<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.3/proj4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/1.0.1/proj4leaflet.min.js"></script>

然后用创建图层

var geojsonLayer = L.Proj.geoJson(myGardenJson);

让代码读取GeoJSON文件的投影内容,然后动态地重新投影数据。顺便说一句, Leaflet 内部使用所有数据的像素坐标,因此它可以理解相对于地图窗格坐标系的位置。这意味着在加载矢量数据时,总是需要一个转换过程,而与数据的投影无关。

您可以将QGIS中的任何矢量层保存为GeoJSON,大多数Web 制图api都提供了易于使用的类,将GeoJSON作为矢量显示格式。在专有软件领域,Esri已经开始支持GeoJSON,并提供了自己的支持JSON-based geometry formats 作为GeoServices REST规范和ArcGIS REST API的一部分;然而,Esri非正式地共享了open source JavaScript library 在两种格式之间转换。

GeoJSON规范不是OGC规范。在撰写本文时,OGC明显缺乏用于定义矢量GIS对象的基于JSON的规范(OGC发布了矢量的基于XML的GML规范)。缺少OGC认可的JSON规范在FOSS社区2013年关于OGC是否应采用Esri生成的GeoServices REST规范的辩论中发挥了作用。该规范本来可以为OGC提供基于JSON的GIS数据格式,但有些人对该格式与专有软件公司的关联有所警惕。geoMusings “ OGC放弃网络” <https://blog.geomusings.com/2013/05/30/ogc-abandons-the-web/>`博客文章就此事件向一位FOSS地理开发人员发表了意见 (也请阅读评论)。