访问量: 434 次浏览
地理信息系统 (GIS) 近年来得到了广泛的关注。 事实上,在160多年前, 地理空间数据就已确定了1854年致命的伦敦霍乱爆发的源头, 并在其中发挥了重要的作用。约翰·斯诺医生是当地的一名医生, 他冒着生命危险, 对霍乱的起因、来源和传播途径进行了跟踪式调查和研究, 证明霍乱不是通过空气,而是带病毒患者的排泄物和粪便, 经下水道溢出污染了饮用水传播的, 并绘制了霍乱病例密度图。 这个观点与当时的传统观念完全不同, 正是他凭着正义感、敬业和执着,拯救了众多英国人的生命。
今天,本文将介绍5个现代开源地图工具, 帮助大家使用 Reaction 和其他开源工具构建 GIS 应用程序。
首先我们需要了解一下可以让地图绘制工作变得更容易的5个基本工具。
如果您刚刚接触 JavaScript 和 Reaction 系统, 那么首先需要在 React 中创建 “Hello World” 应用程序, 在编写第一行 JavaScript 代码之前,需要组装几个库和配置。 Create React App 应用程序在此过程中起到了决定性的作用, Facebook React 团队开发的命令行工具采用 “batteries-included” 方法, 通过包含所有必要的库、启动程序文件甚至单元测试框架, 帮助快速创建功能齐全的 React 应用程序。
GeoJSON 是一种可读的格式, 用于描述和共享 GIS 数据, 并受到许多地理空间库和应用程序的广泛支持, GeoJSON.io 站点是 GeoJSON 数据的在线沙箱。
例如,可以这样描述比萨斜塔的位置:
{
"type": "Feature",
"properties": {
"description": "Leaning Tower of Pisa"
},
"geometry": {
"type": "Point",
"coordinates": [10.39659, 43.72305]
}
}
Leaflet 是用于移动端交互地图的主要开源 JavaScript 库。 JS 库的大小为38k左右, 但是拥有大部分开发者需要的全部地图功能。 Leaflet 保持着简单、性能和实用性的设计思想。 它可以在所有主要的桌面和移动端平台上高效的运转, 可以扩展插件,它有一个易用和文档清晰的 API, 还有一个简单、易读的源代码, 它使地理信息系统大众化, 并将地理地图引入网络应用程序。 该库由 Vladimir Agafonkin 于2012年创建, 自此后已成为用于构建地图的事实上的开源 JavaScript 库, API 很容易使用。
美国加利福尼亚州使用 leaflet 和热图插件构建的户外攀岩墙热图
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);
OpenStreetMap (简称 OSM,中文是公开地图) 是一个网上地图协作计划, 目标是创造一个内容自由且能让所有人编辑的世界地图。 OpenStreetMap 由史蒂夫·科斯特于2004年创立, 是全球最大的协同地图项目。 与维基百科类似, 该平台通过添加和标记当地的道路、高速公路、建筑、河流等, 很容易的绘制出我们周围的世界地图。 这些地图数据在开放许可下可用。 此教程应用程序能够直接连接到 OpenStreetMap 的 REST API 服务器以获取布拉格的所有城堡。 商业用户可以下载 “weekly planet file”, 这是它整个数据库的导出,数据文件大约 40GB 。
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 应用程序, 那么首先让我们创建一个城堡探索器应用程序。
按照 Create React App 存储库中的说明创建工作的 React 应用程序。
# mkdir react-map
# cd react-map
# create-react-app.
这将生成一个新的项目结构。 请注意以下两个文件,因为需要在下一步中进行编辑。
使用以下命令启动应程序:
# npm start
在浏览器中验证该应用程序是否在 http://localhost:3000 上运行。
接下来,在项目中引入 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>
在 Leaflet 中制作地图的方法在概念上类似于在 GIMP 或 Photoshop 中使用图层的方式。 要显示自定义数据,例如兴趣点标记, 请将其添加到 Leaflet 图层, 然后将该图层添加到 Leaflet 地图。
render() {
return (
<Map >
<TileLayer url="tile server url"/>
<YourDataLayerComponent/>
</Map>
);
}
创建一个新的地图组件并将地图以捷克共和国布拉格为中心。 通过编辑 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 内容替换为以下内容:
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。
在此步骤中,将提取 historic=castle 在 OpenStreetMap 中标记的建筑结构, 并将其显示在地图上, 可以使用以下命令 query-overpass 获取从 OpenStreetMap 的 API 服务器获取数据的库,
#npm i --save query-overpass
在 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 中将城堡组件添加到地图中:
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公里范围内的城堡。 您可以改进城堡组件和查询以处理任意纬度和经度, 从而有效地将应用程序转变为全球城堡浏览器!