在本文中,我们将大致了解正向地理编码和反向地理编码的概念。 我们将使用 Mapbox 和 Vue.js 2.6.11 构建一个应用这些概念来显示特定位置的应用程序。
什么是地理编码?
地理编码是将基于文本的位置转换为世界位置的地理坐标(通常为经度和纬度)。
地理编码有两种类型:正向和反向。 正向地理编码将位置文本转换为地理坐标,而反向地理编码将坐标转换为位置文本。
我们的应用程序将具有以下基本功能:
- 允许用户访问带有标记的交互式地图显示;
- 允许用户随意移动标记,同时显示坐标;
- 根据用户请求返回基于文本的位置或位置坐标。
使用 Vue CLI 开启项目
它包含一个带有 Vue CLI 和 yarn 作为包管理器的新项目。 你需要克隆该仓库,并确保你使用的是 geocoder/boilerplate
分支。
设置应用程序的文件结构
接下来,我们需要设置项目的文件结构。 将组件文件夹中的 Helloworld.vue
文件重命名为 Index.vue
。 并将以下内容复制到 App.vue 文件中:
<template>
<div id="app">
<!--Navbar Here -->
<div>
<nav>
<div class="header">
<h3>Geocoder</h3>
</div>
</nav>
</div>
<!--Index Page Here -->
<index />
</div>
</template>
<script>
import index from "./components/index.vue";
export default {
name: "App",
components: {
index,
},
};
</script>
在这里,我们已经导入并在本地注册了最近重命名的组件。 我们还添加了一个导航栏来提升我们应用的美感。
我们需要一个 .env
文件来加载环境变量。 继续在项目文件夹的根目录中添加一个。
安装所需的包和库
接下来,我们需要安装所需的库。 这是我们将用于此项目的列表:
- Mapbox GL JS
- Mapbox-gl-geocoder
- Dotenv
- Axios
根据你首选的包管理器在 CLI 中安装包。 如果你使用 Yarn,请运行以下命令:
代码语言:javascript复制cd geocoder && yarn add mapbox-gl @mapbox/mapbox-gl-geocoder axios
or
代码语言:javascript复制cd geocoder && npm i mapbox-gl @mapbox/mapbox-gl-geocoder axios --save
在运行安装命令之前,我们首先必须进入 geocoder
文件夹。
使用 Vue 搭建前端
让我们继续为我们的应用程序创建一个布局。 我们需要一个元素来容纳我们的地图,一个区域来显示坐标,同时监听标记在地图上的移动,以及在我们调用反向地理编码 API 时显示位置的东西。 我们可以将所有这些都包含在一个卡片组件中。
将以下内容复制到你的 Index.vue
文件中:
<template>
<div class="main">
<div class="flex">
<!-- Map Display here -->
<div class="map-holder">
<div id="map"></div>
</div>
<!-- Coordinates Display here -->
<div class="dislpay-arena">
<div class="coordinates-header">
<h3>Current Coordinates</h3>
<p>Latitude:</p>
<p>Longitude:</p>
</div>
<div class="coordinates-header">
<h3>Current Location</h3>
<div class="form-group">
<input
type="text"
class="location-control"
:value="location"
readonly
/>
<button type="button" class="copy-btn">Copy</button>
</div>
<button type="button" class="location-btn">Get Location</button>
</div>
</div>
</div>
</div>
</template>
启动开发服务器,查看我们目前拥有的内容:
代码语言:javascript复制yarn serve
or
代码语言:javascript复制npm run serve
我们的应用程序现在应该是这样的:
左边的空白点看起来不对。 它应该容纳我们的地图显示。 接下来,让我们继续补充一下。
使用 Mapbox 进行交互式地图显示
我们需要做的第一件事是访问 Mapbox GL 和 Geocoder
库。 我们将首先在 Index.vue
文件中导入 Mapbox GL 和 Geocoder 库
。
import axios from "axios";
import mapboxgl from "mapbox-gl";
import MapboxGeocoder from "@mapbox/mapbox-gl-geocoder";
import "@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css";
Mapbox 需要一个唯一的访问令牌来计算地图矢量。 获取你的 token,并将其作为环境变量添加到你的 .env
文件中。
VUE_APP_MAP_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
我们还需要定义有助于将地图图块放在数据实例中的属性。 在我们导入库的位置下方添加以下内容:
代码语言:javascript复制export default {
data() {
return {
loading: false,
location: "",
access_token: process.env.VUE_APP_MAP_ACCESS_TOKEN,
center: [0, 0],
map: {},
};
},
}
- location 属性将被建模为我们在脚手架中的输入。 我们将使用它来处理反向地理编码(即显示坐标中的位置)。
- center 属性包含我们的坐标(经度和纬度)。 正如我们稍后将看到的,这对于将我们的地图图块放在一起至关重要。
- access_token 属性指的是我们之前添加的环境变量。
- map 属性充当我们地图组件的构造函数。
让我们继续创建一个方法来绘制我们的交互式地图,其中嵌入了我们的正向地理编码器。 这个方法是我们的基础函数,充当我们的组件和 Mapbox GL
之间的中介; 我们将调用这个方法 createMap
。 在数据对象下面添加:
mounted() {
this.createMap()
},
methods: {
async createMap() {
try {
mapboxgl.accessToken = this.access_token;
this.map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
center: this.center,
zoom: 11,
});
} catch (err) {
console.log("map error", err);
}
},
},
为了创建我们的地图,我们指定了一个容纳地图的容器、一个用于地图显示格式的 style
属性以及一个用于容纳坐标的 center
属性。 center
属性是一个数组类型,保存经度和纬度。
Mapbox GL JS 根据页面上的这些参数初始化我们的地图,并返回一个 Map 对象给我们。 Map 对象引用我们页面上的地图,同时公开使我们能够与地图交互的方法和属性。 我们已将此返回的对象存储在我们的数据实例 this.map
中。
使用 Mapbox 地理编码器进行前向地理编码
现在,我们将添加地理编码器和自定义标记。 地理编码器
通过将基于文本的位置转换为坐标来处理正向地理编码。 这将以附加到我们地图的搜索输入框的形式出现。
在我们上面的 this.map
初始化下面添加以下内容:
let geocoder = new MapboxGeocoder({
accessToken: this.access_token,
mapboxgl: mapboxgl,
marker: false,
});
this.map.addControl(geocoder);
geocoder.on("result", (e) => {
const marker = new mapboxgl.Marker({
draggable: true,
color: "#D80739",
})
.setLngLat(e.result.center)
.addTo(this.map);
this.center = e.result.center;
marker.on("dragend", (e) => {
this.center = Object.values(e.target.getLngLat());
});
});
在这里,我们首先使用 MapboxGeocoder
构造函数创建了一个新的地理编码器实例。 这会根据提供的参数初始化地理编码器,并返回一个对象,暴露给方法和事件。 accessToken 属性指的是我们的 Mapbox 访问令牌,mapboxgl
指的是当前使用的地图库。
我们应用的核心是自定义标记;地理编码器默认带有一个。然而,这并不能为我们提供所需的所有定制。因此,我们禁用了它。
继续前进,我们将新创建的地理编码器作为参数传递给 addControl 方法,由我们的地图对象公开给我们。 addControl 接受一个控件作为参数。
为了创建我们的自定义标记,我们使用了地理编码器对象向我们公开的事件。 on 事件侦听器使我们能够订阅地理编码器中发生的事件。它接受各种事件作为参数。我们正在监听 result 事件,该事件在设置输入时触发。
简而言之,在结果上,我们的标记构造函数根据我们提供的参数(在本例中为可拖动属性和颜色)创建一个标记。它返回一个对象,我们使用 setLngLat 方法来获取我们的坐标。我们使用 addTo 方法将自定义标记附加到现有地图。最后,我们用新坐标更新实例中的 center 属性。
我们还必须跟踪自定义标记的移动。 我们通过使用 dragend 事件监听器实现了这一点,并且我们用当前坐标更新了我们的 center 属性。
让我们更新模板以显示我们的交互式地图和转发地理编码器。 使用以下内容更新我们模板中的坐标显示部分:
代码语言:javascript复制<div class="coordinates-header">
<h3>Current Coordinates</h3>
<p>Latitude: {{ center[0] }}</p>
<p>Longitude: {{ center[1] }}</p>
</div>
还记得我们如何总是在事件发生后更新我们的中心属性吗? 我们在这里根据当前值显示坐标。
为了提升我们应用的美感,在 index.html
文件的 head
部分添加以下 CSS 文件。 将此文件放在公用文件夹中。
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css" rel="stylesheet" />
使用 Mapbox API 反向地理编码位置
现在,我们将处理反向地理编码我们的坐标到基于文本的位置。 让我们编写一个方法来处理它并使用模板中的 Get Location 按钮触发它。
Mapbox 中的反向地理编码由反向地理编码 API 处理。 这接受经度、纬度和访问令牌作为请求参数。 此调用返回响应负载——通常带有各种详细信息。 我们关注的是特征数组中的第一个对象,即反向地理编码位置所在的位置。
我们需要创建一个函数,将我们想要到达的位置的经度、纬度和 access_token
发送到 Mapbox API。 我们需要发送它们以获取该位置的详细信息。
最后,我们需要使用对象中 place_name
键的值更新实例中的 location
属性。
在 createMap() 函数下面,让我们添加一个新函数来处理我们想要的。 它应该是这样的:
代码语言:javascript复制async getLocation() {
try {
this.loading = true;
const response = await axios.get(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${this.center[0]},${this.center[1]}.json?access_token=${this.access_token}`
);
this.loading = false;
this.location = response.data.features[0].place_name;
} catch (err) {
this.loading = false;
console.log(err);
}
},
该函数向 Mapbox API 发出 GET 请求。 响应包含 place_name — 所选位置的名称。 我们从响应中获取它,然后将其设置为 this.location
的值。
完成后,我们需要编辑和设置将调用我们创建的这个函数的按钮。 我们将使用一个点击事件监听器——当用户点击它时它会调用 getLocation
方法。 继续并将按钮组件编辑为此。
<button
type="button"
:disabled="loading"
:class="{ disabled: loading }"
class="location-btn"
@click="getLocation"
>
Get Location
</button>
接着,让我们附加一个将显示的位置复制到剪贴板
的功能。 在 getLocation
函数下方添加:
copyLocation() {
if (this.location) {
navigator.clipboard.writeText(this.location);
alert("Location Copied")
}
return;
},
更新 Copy
按钮组件以触发此操作:
<button type="button" class="copy-btn" @click="copyLocation">
结尾
在本文中,我们研究了使用 Mapbox 进行地理编码。 我们构建了一个地理编码应用程序,它将基于文本的位置转换为坐标,在交互式地图上显示位置,并根据用户的请求将坐标转换为基于文本的位置。