5 个快速构建地图应用程序的开源工具


发布日期 : 2022-07-06 01:03:53 UTC

<center>gis_cholera_map</center>

地理信息系统 (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 数据的在线沙箱。

例如,可以这样描述比萨斜塔的位置:

{
    &quot;type&quot;: &quot;Feature&quot;,
    &quot;properties&quot;: {
        &quot;description&quot;: &quot;Leaning Tower of Pisa&quot;
    },
    &quot;geometry&quot;: {
        &quot;type&quot;: &quot;Point&quot;,
        &quot;coordinates&quot;: [10.39659, 43.72305]
    }
}

<center>gis_geojson_0</center>

3. Leaflet

Leaflet 是用于移动端交互地图的主要开源 JavaScript 库。 JS 库的大小为38k左右, 但是拥有大部分开发者需要的全部地图功能。 Leaflet 保持着简单、性能和实用性的设计思想。 它可以在所有主要的桌面和移动端平台上高效的运转, 可以扩展插件,它有一个易用和文档清晰的 API, 还有一个简单、易读的源代码, 它使地理信息系统大众化, 并将地理地图引入网络应用程序。 该库由 Vladimir Agafonkin 于2012年创建, 自此后已成为用于构建地图的事实上的开源 JavaScript 库, API 很容易使用。

<center>gis_leaflet_0</center>

美国加利福尼亚州使用 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: &#39;miles&#39;};

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=&quot;Praha&quot;];
(
  way[historic=castle](around:10000);
  relation[historic=castle](around:10000);
);
out body;
&gt;;
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

<center>gis_welcometoreact_0</center>

在浏览器中验证该应用程序是否在 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 内呈现。

&lt;head&gt;
   ...  
   &lt;link rel=&quot;stylesheet&quot; href=&quot;https://unpkg.com/leaflet@1.3.1/dist/leaflet.css&quot; integrity=&quot;sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==&quot;/&gt;

   &lt;style&gt;
       .leaflet-container {
         height: 650px;
         width: 800px;
       }
   &lt;/style&gt;
   ...
&lt;/head&gt;

3.创建第一个地图组件

在 Leaflet 中制作地图的方法在概念上类似于在 GIMP 或 Photoshop 中使用图层的方式。 要显示自定义数据,例如兴​​趣点标记, 请将其添加到 Leaflet 图层, 然后将该图层添加到 Leaflet 地图。

render() {
   return (
     &lt;Map &gt;
       &lt;TileLayer url=&quot;tile server url&quot;/&gt;
       &lt;YourDataLayerComponent/&gt;
     &lt;/Map&gt;
    );
 }

创建一个新的地图组件并将地图以捷克共和国布拉格为中心。 通过编辑 MyMap.js 在市中心放置一个标记,如下所示:

src/MyMap.js
import React from &quot;react&quot;;
import { Map, TileLayer, Marker } from &quot;react-leaflet&quot;;

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 (
     &lt;Map center={position} zoom={this.state.zoom}&gt;
       &lt;TileLayer
         attribution=&quot;© &lt;a href=&quot;http://osm.org/copyright&quot;&gt;OpenStreetMap&lt;/a&gt; contributors&quot;
         url=&quot;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&quot;
       /&gt;
       &lt;Marker position={[this.state.lat, this.state.lng]} /&gt;

     &lt;/Map&gt;
   );
 }
}

现在可以将 MyMap 组件连接到项目的入口点组件, 只需将 App.js 内容替换为以下内容:

src/App.js
import React, { Component } from &quot;react&quot;;
import MyMap from &quot;./MyMap&quot;;

class App extends Component {
 render() {
   return &lt;MyMap /&gt;;
 }
}
export default App;

浏览器现在应该显示布拉格地图, 可以使用鼠标缩放和平移地图。

<center>gis_prague_0</center>

更多详情请在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 &quot;react&quot;;
import { GeoJSON, Marker } from &quot;react-leaflet&quot;;
import * as overpass from &quot;query-overpass&quot;;

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;&gt;;out skel qt;`;
   const options = {
     flatProperties: true
   };
   overpass(query, this.dataHandler, options);
 }

 dataHandler = (error, osmData) =&gt; {
   if (!error &amp;&amp; osmData.features !== undefined) {
     this.setState({ geojson: osmData });
   }
 };

 render() {
   return this.state.geojson ? &lt;GeoJSON data={this.state.geojson} /&gt; : null;
 }
}

在 MyMap.js 中将城堡组件添加到地图中:

src/MyMap.js
import Castles from &quot;./Castles&quot;;
...
 render() {
   const position = [this.state.lat, this.state.lng];
   return (
     &lt;Map center={position} zoom={this.state.zoom}&gt;
       &lt;TileLayer
         attribution=&quot;© &lt;a href=&quot;http://osm.org/copyright&quot;&gt;OpenStreetMap&lt;/a&gt; contributors&quot;
         url=&quot;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&quot;
       /&gt;
       &lt;Marker position={[this.state.lat, this.state.lng]} /&gt;
       &lt;Castles /&gt;
     &lt;/Map&gt;
   );
 }

<center>gis_castles_0</center>

请查阅关于 codesandbox.io 的完整项目。

最后一步

如果检查从 Overpass 返回的 JSON, 您将会看到大量的信息, 例如每个城堡的物理地址, 捷克语中的名称以及维基百科文章等。 您可以添加一个弹出窗口, 以便在用户单击城堡时显示其他详细信息。

此外,该查询是硬编码的, 用于搜索布拉格市中心半径10公里范围内的城堡。 您可以改进城堡组件和查询以处理任意纬度和经度, 从而有效地将应用程序转变为全球城堡浏览器!