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

了解如何使用 React 和其他开源工具构建 GIS 应用。
382 位读者喜欢这篇文章。
cholera map

维基百科,公共领域

近年来,地理信息系统 (GIS) 受到的广泛关注可能会让你认为它们是新鲜事物。事实上,早在 160 多年前,地理空间数据就在识别致命的 1854 年伦敦霍乱疫情 的源头方面发挥了重要作用。当地医生约翰·斯诺博士怀疑饮用水污染是疾病的根源。在调查期间,他绘制了霍乱病例的密度图,并采访了受影响社区的居民,了解他们的用水习惯。他的分析显示,公共水泵附近的发病率很高。

在本文中,我将介绍五个现代开源地图工具,并帮助你开始构建你的第一个 GIS 应用。

构建你的第一个 GIS 应用之前需要了解的 5 个工具

在深入了解如何构建你的第一个 GIS 应用(捷克共和国布拉格城堡地图)的教程之前,让我们先来看看五个可以简化你的地图制作生活的必备工具。

1. Create React App

如果你是 JavaScript 和 React 生态系统的新手,从头开始创建一个 React “Hello World” 应用对于胆小者来说并非易事。在你可以编写你的第一行 JavaScript 代码之前,需要组装多个库和配置。

幸运的是,Create React App 来解救你了。这款由 Facebook React 团队开发的命令行工具采用了“开箱即用”的方法,通过包含所有必要的库、入门文件,甚至单元测试框架,帮助你快速创建一个功能齐全的 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]
    }
}

要查看你的 GeoJSON 数据在地图上的外观,请访问 GeoJSON.io 并输入上述代码。

3. Leaflet

如果我可以将功劳归于一个开源库,因为它普及了 GIS 并将地理地图带入 Web 应用,那么这个奖项将授予 Leaflet.js。该库由 Vladimir Agafonkin 于 2012 年创建,此后已成为构建地图的事实上的开源 JavaScript 库。API 易于使用且文档完善,如果你遇到任何困难,Web 和 StackOverflow 上都有庞大的社区。

美国加利福尼亚州户外攀岩墙的热图。使用 Leaflet 和 Heatmap 插件构建。

4. Turf.js

Turf.js 是一个强大的地理空间库,可以包含在你的工具箱中。你可以执行常见的地理空间函数,例如测试一个点是否位于多边形内,或者执行更复杂的 k-means 计算,为热图准备数据。

例如,以下代码将计算旧金山和东京成田机场之间的距离

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

OpenStreetMapSteve Coast 于 2004 年创立,是世界上最大的协作地图项目。与维基百科类似,该平台使像你我这样的人可以轻松地绘制我们周围的世界地图,方法是添加和标记当地的道路、高速公路、建筑物、河流等等。这些地图数据根据开放许可提供,是 GIS 应用的金矿!我们的教程应用将直接连接到 OpenStreetMap 的 REST API 服务器,以获取布拉格的所有城堡。商业用户可以下载其“每周地球文件”,这是其整个数据库的导出,一个大约 40GB 的数据文件。

Overpass-Turbo

Overpass-turbo 是一个交互式站点,用于尝试针对 OpenStreetMap 数据库的查询。要查看布拉格市中心 10 公里范围内的所有城堡,请输入以下查询,然后单击“运行”。请注意,地图不会自动缩放到我们的搜索结果。你必须在搜索框中输入“Prague”以使地图居中。

[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: 应用程序的主 index.html
  • src/App.js: React 组件的入口点

使用以下命令启动应用

# npm start

2. 设置 Leaflet 库和 React 包装器

接下来,将 Leaflet 和 React-Leaflet 引入项目。后者是一个包装器库,使 Leaflet 能够作为 React 组件工作。

使用以下命令安装 Leaflet 和 React-Leaflet

#npm install --save react-leaflet leaflet

在你的项目中找到 public/index.html,并添加指向 leaflet.css 的链接,以及一些用于主 Leaflet div 的定位 CSS。地图将在此 div 容器内呈现。

<head>
   ...   
   <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"/>

   <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="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
         url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
       />
       <Marker position={[this.state.lat, this.state.lng]} />

     </Map>
   );
 }
}

现在你可以通过简单地将 App.js 内容替换为以下内容,将 MyMap 组件连接到项目的入口点组件

src/App.js

import React, { Component } from "react";
import MyMap from "./MyMap";

class App extends Component {
 render() {
   return <MyMap />;
 }
}
export default App;

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

4. 在地图上显示城堡

在此步骤中,你将提取在 OpenStreetMap 中标记为 historic=castle 的建筑物结构,并在你的地图上显示它们。你可以使用 query-overpass 库,而不是滚动你自己的 Rest API 客户端,该库从 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="&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
         url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
       />
       <Marker position={[this.state.lat, this.state.lng]} />
       <Castles />
     </Map>
   );
 }

 

下一步是什么?

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

此外,该查询被硬编码为搜索布拉格市中心 10 公里半径内的城堡。你可以改进城堡组件和查询,以处理任意纬度和经度,从而有效地将该应用变成一个全球城堡探索器!

User profile image.
Viet Nguyen 是一位攀岩爱好者和 GIS 爱好者。他目前是 Kiali 项目的团队成员。

3 条评论

谢谢你,Viet!
我更改了 MyMap.js 中的 lat 和 lng - 它渲染正常,但只显示了六分之一的瓦片。我在另一个国家第二次尝试检查它是否与位置有关,但同样的问题仍然存在。
有什么建议吗?
祝一切顺利

@nobicycle 感谢你查看演示应用。你可以转到浏览器的开发者工具 -> 网络选项卡,并检查是否所有 .png 瓦片文件都已加载且没有错误?

很棒的文章,而且呈现得非常好。让我很想放下工作,直接开始探索 GIS 的东西 :-)

© 2025 open-source.net.cn. All rights reserved.