• 使用 Mapbox 在 Vue 中开发一个地理信息定位应用


    ⭐️ 本文首发自 前端修罗场(点击加入),是一个由 资深开发者 独立运行 的专业技术社区,我专注 Web 技术、Web3、区块链、答疑解惑、面试辅导以及职业发展博主创作的 《前端面试复习笔记》(点击订阅),广受好评,已帮助多人提升实力、拿到 offer。现在订阅,私聊博主即可获取一次 免费的模拟面试/简历指导服务,帮你评估知识点的掌握程度,获得更全面的学习指导意见!

    在本文中,我们将大致了解正向地理编码和反向地理编码的概念。 我们将使用 Mapbox 和 Vue.js 2.6.11 构建一个应用这些概念来显示特定位置的应用程序。

    什么是地理编码?

    地理编码是将基于文本的位置转换为世界位置的地理坐标(通常为经度和纬度)。

    地理编码有两种类型:正向和反向。 正向地理编码将位置文本转换为地理坐标,而反向地理编码将坐标转换为位置文本。

    我们的应用程序将具有以下基本功能:

    • 允许用户访问带有标记的交互式地图显示;
    • 允许用户随意移动标记,同时显示坐标;
    • 根据用户请求返回基于文本的位置或位置坐标。

    使用 Vue CLI 开启项目

    我们将使用此存储库中的样板代码进行开发。 它包含一个带有 Vue CLI 和 yarn 作为包管理器的新项目。 你需要克隆该仓库,并确保你使用的是 geocoder/boilerplate 分支。

    设置应用程序的文件结构

    接下来,我们需要设置项目的文件结构。 将组件文件夹中的 Helloworld.vue 文件重命名为 Index.vue。 并将以下内容复制到 App.vue 文件中:

    <template>
      <div id="app">
        
        <div>
          <nav>
            <div class="header">
              <h3>Geocoderh3>
            div>
          nav>
        div>
        
        <index />
      div>
    template>
    <script>
    import index from "./components/index.vue";
    export default {
      name: "App",
      components: {
        index,
      },
    };
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里,我们已经导入并在本地注册了最近重命名的组件。 我们还添加了一个导航栏来提升我们应用的美感。

    我们需要一个 .env 文件来加载环境变量。 继续在项目文件夹的根目录中添加一个。

    安装所需的包和库

    接下来,我们需要安装所需的库。 这是我们将用于此项目的列表:

    • Mapbox GL JS
    • Mapbox-gl-geocoder
    • Dotenv
    • Axios

    根据你首选的包管理器在 CLI 中安装包。 如果你使用 Yarn,请运行以下命令:

    cd geocoder && yarn add mapbox-gl @mapbox/mapbox-gl-geocoder axios
    
    • 1

    or

    cd geocoder && npm i mapbox-gl @mapbox/mapbox-gl-geocoder axios --save
    
    • 1

    在运行安装命令之前,我们首先必须进入 geocoder 文件夹。

    使用 Vue 搭建前端

    让我们继续为我们的应用程序创建一个布局。 我们需要一个元素来容纳我们的地图,一个区域来显示坐标,同时监听标记在地图上的移动,以及在我们调用反向地理编码 API 时显示位置的东西。 我们可以将所有这些都包含在一个卡片组件中。

    将以下内容复制到你的 Index.vue 文件中:

    <template>
      <div class="main">
        <div class="flex">
          
          <div class="map-holder">
            <div id="map">div>
          div>
          
          <div class="dislpay-arena">
            <div class="coordinates-header">
              <h3>Current Coordinatesh3>
              <p>Latitude:p>
              <p>Longitude:p>
            div>
            <div class="coordinates-header">
              <h3>Current Locationh3>
              <div class="form-group">
                <input
                  type="text"
                  class="location-control"
                  :value="location"
                  readonly
                />
                <button type="button" class="copy-btn">Copybutton>
              div>
              <button type="button" class="location-btn">Get Locationbutton>
            div>
          div>
        div>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    启动开发服务器,查看我们目前拥有的内容:

    yarn serve
    
    • 1

    or

    npm run serve
    
    • 1

    我们的应用程序现在应该是这样的:

    在这里插入图片描述
    左边的空白点看起来不对。 它应该容纳我们的地图显示。 接下来,让我们继续补充一下。

    使用 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";
    
    • 1
    • 2
    • 3
    • 4

    Mapbox 需要一个唯一的访问令牌来计算地图矢量。 获取你的 token,并将其作为环境变量添加到你的 .env 文件中。

    VUE_APP_MAP_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    
    • 1

    我们还需要定义有助于将地图图块放在数据实例中的属性。 在我们导入库的位置下方添加以下内容:

    export default {
      data() {
        return {
          loading: false,
          location: "",
          access_token: process.env.VUE_APP_MAP_ACCESS_TOKEN,
          center: [0, 0],
          map: {},
        };
      },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 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);
        }
      },
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    为了创建我们的地图,我们指定了一个容纳地图的容器、一个用于地图显示格式的 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());
      });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里,我们首先使用 MapboxGeocoder 构造函数创建了一个新的地理编码器实例。 这会根据提供的参数初始化地理编码器,并返回一个对象,暴露给方法和事件。 accessToken 属性指的是我们的 Mapbox 访问令牌,mapboxgl 指的是当前使用的地图库

    我们应用的核心是自定义标记;地理编码器默认带有一个。然而,这并不能为我们提供所需的所有定制。因此,我们禁用了它。

    继续前进,我们将新创建的地理编码器作为参数传递给 addControl 方法,由我们的地图对象公开给我们。 addControl 接受一个控件作为参数。

    为了创建我们的自定义标记,我们使用了地理编码器对象向我们公开的事件。 on 事件侦听器使我们能够订阅地理编码器中发生的事件。它接受各种事件作为参数。我们正在监听 result 事件,该事件在设置输入时触发。

    简而言之,在结果上,我们的标记构造函数根据我们提供的参数(在本例中为可拖动属性和颜色)创建一个标记。它返回一个对象,我们使用 setLngLat 方法来获取我们的坐标。我们使用 addTo 方法将自定义标记附加到现有地图。最后,我们用新坐标更新实例中的 center 属性。

    我们还必须跟踪自定义标记的移动。 我们通过使用 dragend 事件监听器实现了这一点,并且我们用当前坐标更新了我们的 center 属性。

    让我们更新模板以显示我们的交互式地图和转发地理编码器。 使用以下内容更新我们模板中的坐标显示部分:

    <div class="coordinates-header">
      <h3>Current Coordinatesh3>
      <p>Latitude: {{ center[0] }}p>
      <p>Longitude: {{ center[1] }}p>
    div>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    还记得我们如何总是在事件发生后更新我们的中心属性吗? 我们在这里根据当前值显示坐标。

    为了提升我们应用的美感,在 index.html 文件的 head 部分添加以下 CSS 文件。 将此文件放在公用文件夹中。

    <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css" rel="stylesheet" />
    
    • 1

    在这里插入图片描述

    使用 Mapbox API 反向地理编码位置

    现在,我们将处理反向地理编码我们的坐标到基于文本的位置。 让我们编写一个方法来处理它并使用模板中的 Get Location 按钮触发它。

    Mapbox 中的反向地理编码由反向地理编码 API 处理。 这接受经度、纬度和访问令牌作为请求参数。 此调用返回响应负载——通常带有各种详细信息。 我们关注的是特征数组中的第一个对象,即反向地理编码位置所在的位置。

    我们需要创建一个函数,将我们想要到达的位置的经度、纬度和 access_token 发送到 Mapbox API。 我们需要发送它们以获取该位置的详细信息。

    最后,我们需要使用对象中 place_name 键的值更新实例中的 location 属性。

    在 createMap() 函数下面,让我们添加一个新函数来处理我们想要的。 它应该是这样的:

    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);
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    该函数向 Mapbox API 发出 GET 请求。 响应包含 place_name — 所选位置的名称。 我们从响应中获取它,然后将其设置为 this.location 的值。

    完成后,我们需要编辑和设置将调用我们创建的这个函数的按钮。 我们将使用一个点击事件监听器——当用户点击它时它会调用 getLocation 方法。 继续并将按钮组件编辑为此。

    <button
      type="button"
      :disabled="loading"
      :class="{ disabled: loading }"
      class="location-btn"
      @click="getLocation"
    >
      Get Location
    button>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接着,让我们附加一个将显示的位置复制到剪贴板的功能。 在 getLocation 函数下方添加:

    copyLocation() {
      if (this.location) {
        navigator.clipboard.writeText(this.location);
        alert("Location Copied")
      }
      return;
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    更新 Copy 按钮组件以触发此操作:

    <button type="button" class="copy-btn" @click="copyLocation">
    
    • 1

    结尾

    在本文中,我们研究了使用 Mapbox 进行地理编码。 我们构建了一个地理编码应用程序,它将基于文本的位置转换为坐标,在交互式地图上显示位置,并根据用户的请求将坐标转换为基于文本的位置。

  • 相关阅读:
    ElasticSearch 深度分页解决方案
    轻松查找,一键打印:手把手教你做记账明细管理
    LeetCode笔记:Weekly Contest 322
    【愚公系列】2022年7月 Go教学课程 004-Go代码注释
    【无标题】
    昨天
    基于Ruoyi和WebUploader的统一附件管理扩展(上)
    Python处理Excel表格
    Spring Boot集成redis集群拓扑动态刷新
    2022年笔试知识总结展望(前后端均有)
  • 原文地址:https://blog.csdn.net/ImagineCode/article/details/126357935