摘要: 地理信息系统 (GIS) 近年来得到了广泛的关注。事实上,在160多年前,地理空间数据就已确定了1854年致命的伦敦霍乱爆发的源头,并在其中发挥了重要的作用。约翰·斯诺医生是当地的一名医生,他冒着生命危险,对霍乱的起因、来源和传播途径进行了跟踪式调查和研究,...
地理信息系统 (GIS) 近年来得到了广泛的关注。事实上,在160多年前,地理空间数据就已确定了1854年致命的伦敦霍乱爆发的源头,并在其中发挥了重要的作用。约翰·斯诺医生是当地的一名医生,他冒着生命危险,对霍乱的起因、来源和传播途径进行了跟踪式调查和研究,证明霍乱不是通过空气,而是带病毒患者的排泄物和粪便,经下水道溢出污染了饮用水传播的,并绘制了霍乱病例密度图。这个观点与当时的传统观念完全不同,正是他凭着正义感、敬业和执着,拯救了众多英国人的生命。
今天,本文将介绍5个现代开源地图工具,帮助大家使用 Reaction 和其他开源工具构建 GIS 应用程序。
构建 GIS 应用程序之前需要了解的5个工具
首先我们需要了解一下可以让地图绘制工作变得更容易的5个基本工具。
1.创建 Reaction App
如果您刚刚接触 JavaScript 和 Reaction 系统,那么首先需要在 React 中创建 “Hello World” 应用程序,在编写第一行 JavaScript 代码之前,需要组装几个库和配置。Create React App 应用程序在此过程中起到了决定性的作用,Facebook React 团队开发的命令行工具采用 “batteries-included” 方法,通过包含所有必要的库、启动程序文件甚至单元测试框架,帮助快速创建功能齐全的 React 应用程序。
2.GeoJSON.io
GeoJSON 是一种可读的格式,用于描述和共享 GIS 数据,并受到许多地理空间库和应用程序的广泛支持,GeoJSON.io 站点是 GeoJSON 数据的在线沙箱。
例如,可以这样描述比萨斜塔的位置:
{
"type": "Feature",
"properties": {
"description": "Leaning Tower of Pisa"
},
"geometry": {
"type": "Point",
"coordinates": [10.39659, 43.72305]
}
}
3. Leaflet
Leaflet 是用于移动端交互地图的主要开源 JavaScript 库。JS 库的大小为38k左右,但是拥有大部分开发者需要的全部地图功能。Leaflet 保持着简单、性能和实用性的设计思想。它可以在所有主要的桌面和移动端平台上高效的运转,可以扩展插件,它有一个易用和文档清晰的 API,还有一个简单、易读的源代码,它使地理信息系统大众化,并将地理地图引入网络应用程序。该库由 Vladimir Agafonkin 于2012年创建,自此后已成为用于构建地图的事实上的开源 JavaScript 库,API 很容易使用。
美国加利福尼亚州使用 leaflet 和热图插件构建的户外攀岩墙热图
4.Turf.js
Turf.js 是一个用于空间分析的 JavaScript 库。它包括传统的空间操作,用于创建 GeoJSON 数据的帮助函数,以及数据分类和统计工具。 Turfjs 可以作为客户端插件添加到您的网站,也可以使用 Node.js 运行 Turf 服务器端。
Turf.js 可以执行常见的地理空间功能,例如测试点是否位于多边形内,或者进行更复杂的 k- 均值计算,进而为热图准备数据。例如,以下公式将计算旧金山和东京成田机场之间的距离:
const fromSFO = turf.point([-122.3790, 37.6218]);
const toNRT = turf.point([140.3731, 35.7709]);
const options = {units: 'miles'};
var distance = turf.distance(fromSFO, toNRT, options);
5.OpenStreetMap
OpenStreetMap (简称 OSM,中文是公开地图) 是一个网上地图协作计划,目标是创造一个内容自由且能让所有人编辑的世界地图。OpenStreetMap 由史蒂夫·科斯特于2004年创立,是全球最大的协同地图项目。与维基百科类似,该平台通过添加和标记当地的道路、高速公路、建筑、河流等,很容易的绘制出我们周围的世界地图。这些地图数据在开放许可下可用。此教程应用程序能够直接连接到 OpenStreetMap 的 REST API 服务器以获取布拉格的所有城堡。商业用户可以下载 “weekly planet file”,这是它整个数据库的导出,数据文件大约 40GB 。
Overpass-turbo
Overpass-turbo 是一个交互式站点,用于尝试对 OpenStreetMap 数据库进行查询。如要查看布拉格市中心10公里范围内的所有城堡,请输入 “Praha” 查询,然后单击运行。请注意,地图不会自动缩放到我们的搜索结果,必须在搜索框中输入布拉格才能使地图居中。
[out:json];
node[name="Praha"];
(
way[historic=castle](around:10000);
relation[historic=castle](around:10000);
);
out body;
>;
out skel qt;
构建GIS应用程序
要了解如何构建 GIS 应用程序,那么首先让我们创建一个城堡探索器应用程序。
1.使用 Create React App 创建应用程序
按照 Create React App 存储库中的说明创建工作的 React 应用程序。
# mkdir react-map
# cd react-map
# create-react-app.
这将生成一个新的项目结构。请注意以下两个文件,因为需要在下一步中进行编辑。
- Public/index.html:应用程序的主索引.html;
- SRC/App.js:React 组件的入口点
使用以下命令启动应程序:
# npm start
在浏览器中验证该应用程序是否在 http://localhost:3000 上运行。
2.设置 Leaflet 库和 React 包装器
接下来,在项目中引入 Leaflet 和 React-Leaflet。后者是一个包装库,令 Leaflet 可以作为 React 组件工作。
使用以下命令安装 Leaflet 和 React-Leaflet:
#npm install --save react-leaflet leaflet
在项目中找到 public/index.html
并添加指向 leaflet.cssde
的主链接以及定位 CSS div
。地图将在此 div
内呈现。
<head>
...
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="/>
<style>
.leaflet-container {
height: 650px;
width: 800px;
}
</style>
...
</head>
3.创建第一个地图组件
在 Leaflet 中制作地图的方法在概念上类似于在 GIMP 或 Photoshop 中使用图层的方式。要显示自定义数据,例如兴趣点标记,请将其添加到 Leaflet 图层,然后将该图层添加到 Leaflet 地图。
render() {
return (
<Map >
<TileLayer url="tile server url"/>
<YourDataLayerComponent/>
</Map>
);
}
创建一个新的地图组件并将地图以捷克共和国布拉格为中心。通过编辑 MyMap.js 在市中心放置一个标记,如下所示:
src/MyMap.js
import React from "react";
import { Map, TileLayer, Marker } from "react-leaflet";
export default class MyMap extends React.Component {
constructor(props) {
super(props);
this.state = {
lat: 50.0893,
lng: 14.4284,
zoom: 12
};
}
render() {
const position = [this.state.lat, this.state.lng];
return (
<Map center={position} zoom={this.state.zoom}>
<TileLayer
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[this.state.lat, this.state.lng]} />
</Map>
);
}
}
现在可以将 MyMap 组件连接到项目的入口点组件,只需将 App.js 内容替换为以下内容:
src/App.js
import React, { Component } from "react";
import MyMap from "./MyMap";
class App extends Component {
render() {
return <MyMap />;
}
}
export default App;
浏览器现在应该显示布拉格地图, 可以使用鼠标缩放和平移地图。
更多详情请在CodePen上查看:https://codepen.io/openbeta/pen/QmdvqP。
4.在地图上显示城堡
在此步骤中,将提取 historic=castle
在 OpenStreetMap 中标记的建筑结构,
并将其显示在地图上,
可以使用以下命令 query-overpass
获取从 OpenStreetMap 的 API 服务器获取数据的库,
#npm i --save query-overpass
在 Castles.js 中为城堡组件创建一个新文件:
src/Castles.js
import React from "react";
import { GeoJSON, Marker } from "react-leaflet";
import * as overpass from "query-overpass";
export default class Castles extends React.Component {
constructor(props) {
super(props);
this.state = {
geojson: undefined
};
}
componentDidMount() {
const query = `[out:json];(way[historic=castle](around:10000, 50.0874654,14.4212535);\
relation[historic=castle](around:10000, 50.0874654,14.4212535););\
out body;>;out skel qt;`;
const options = {
flatProperties: true
};
overpass(query, this.dataHandler, options);
}
dataHandler = (error, osmData) => {
if (!error && osmData.features !== undefined) {
this.setState({ geojson: osmData });
}
};
render() {
return this.state.geojson ? <GeoJSON data={this.state.geojson} /> : null;
}
}
在 MyMap.js 中将城堡组件添加到地图中:
src/MyMap.js
import Castles from "./Castles";
...
render() {
const position = [this.state.lat, this.state.lng];
return (
<Map center={position} zoom={this.state.zoom}>
<TileLayer
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[this.state.lat, this.state.lng]} />
<Castles />
</Map>
);
}
请查阅关于 codesandbox.io 的完整项目。
最后一步
如果检查从 Overpass 返回的 JSON,您将会看到大量的信息,例如每个城堡的物理地址,捷克语中的名称以及维基百科文章等。您可以添加一个弹出窗口,以便在用户单击城堡时显示其他详细信息。
此外,该查询是硬编码的,用于搜索布拉格市中心半径10公里范围内的城堡。您可以改进城堡组件和查询以处理任意纬度和经度,从而有效地将应用程序转变为全球城堡浏览器!