基于 Laravel + Vue 构建 API 驱动的前后端分离应用系列(十六) —— 通过 Vue + 高德地图 JS API 在地图上标记咖啡店

上一篇教程中我们为咖啡店地址进行了地理编码,这样,就可以调用高德地图支持的各种 API 来实现我们想要实现的功能(地图服务都是基于地理编码来实现),在这篇教程中,我们将基于地理编码在地图上标记咖啡店,我们将通过在 Cafes 页面中包含地图组件来实现这个功能。

第一步:获取高德地图 JS API Key

由于是在前端实现地图标记功能,所以需要申请高德地图的 JS API Key,在上一篇教程创建的应用中添加 Key,在弹出页面选择「Web端」即可:

创建完成后即可在应用 Key 列表中看到了。

第二步:将 API Key 添加到 config.js 中

和 Laravel 后端类似,接下来我们将上一步申请的 JS API Key 添加到前端配置文件 resources/assets/js/config.js 中,以便可以全局使用:

/**
 * Defines the API route we are using.
 */
var api_url = '';
var gaode_maps_js_api_key = '{YOUR API KEY HERE}';

switch( process.env.NODE_ENV ){
    case 'development':
        api_url = 'http://roast.test/api/v1';
        break;
    case 'production':
        api_url = 'http://roast.demo.laravelacademy.org/api/v1';
        break;
}

export const ROAST_CONFIG = {
    API_URL: api_url,
    GAODE_MAPS_JS_API_KEY: gaode_maps_js_api_key
};

第三步:添加高德地图脚本到 app.blade.php

高德地图完整的 JS API 文档参考这里:https://lbs.amap.com/api/javascript-api/summary,可以翻阅下这篇文档快速了解 JS API 的使用以及提供的功能。在使用高德地图 JS API 之前,需要先在页面引入 JS API 的入口脚本,由于我们的应用是单页面应用,故而在 resources/views/app.blade.php 中引入即可,这样所有子页面都可以使用高德地图 JS API:

<script src="https://webapi.amap.com/maps?v=1.4.8&key=您申请的key值"></script>

这里为了简化代码逻辑,我们使用的是同步方式引入,你也可以通过异步方式引入,参考高德地图 API 文档即可。

第四步:新增 CafeMap 组件

我们将以 Vue 组件方式展示地图,以便可以插入到不同页面,从而方便复用和维护,为此,我们在 resources/assets/js/components 目录下创建一个 cafes 子目录,然后在该子目录下创建 CafeMap.vue 组件,并编写好组件代码结构:

<style lang="scss">

</style>

<template>
  <div id="cafe-map">

  </div>
</template>

<script>
  export default {

  }
</script>

第五步:添加高德地图到组件

然后我们在 CafeMap.vue 组件中初始化高德地图的绘制,首先来定义高德地图的一些必备属性:

props: {
  'latitude': {  // 经度
      type: Number,
      default: function () {
          return 120.21
      }
  },
  'longitude': {  // 纬度
      type: Number,
      default: function () {
          return 30.29
      }
  },
  'zoom': {   // 缩放级别
      type: Number,
      default: function () {
          return 4
      }
  }
},
data() {
  return {}
},

props 方式从父组件中传递属性数据的好处是方便在不同页面传入不同的属性值,从而提高组件的灵活性,如果你对上述语法不太了解,可参考 Vue 的组件文档

其次定义高德地图显示样式:

<style lang="scss">
    div#cafe-map {
        width: 100%;
        height: 400px;
    }
</style>

最后定义高德地图初始化绘制脚本,我们将在 mounted() 方法中定义这段代码,以便每次页面载入时都会重新绘制地图:

mounted() {
   this.map = new AMap.Map('cafe-map', {
       center: [this.latitude, this.longitude],
       zoom: this.zoom
   });
}

在初始化绘制代码中,我们用到了从父组件传入的经纬度和地图级别等属性,如果父组件没有传入,则使用默认值。

第六步:添加 CafeMap 组件到 Cafes 页面

接下来,我们打开 resrouces/assets/js/pages/Cafes.vue 文件,引入上一步定义的 CafeMap.vue 组件并将其添加到当前页面:

import CafeMap from '../components/cafes/CafeMap.vue';
export default {
    components: {
        CafeMap
    }
}

最后,在 Cafes.vue 页面上编写显示组件的 HTML 代码:

<template>
    <div id="cafes">
        <div class="grid-x">
            <div class="large-9 medium-9 small-12 cell">
                <cafe-map></cafe-map>
            </div>
            <div class="large-3 medium-3 small-12 cell">

            </div>
        </div>
    </div>
</template>

在项目根目录下运行 npm run dev 重新构建项目,访问 http://roast.test,然后点击 Cafes 链接,即可看到这个初始化的地图:

第七步:将咖啡店标记在地图上

最后的最后,也是最关键的一步,我们将在之前创建的 CafeMap.vue 组件中实现咖啡店在高德地图上的位置标记(对应高德地图上的点标记文档)。

打开 resources/assets/js/components/cafes/CafeMap.vue 组件,在模型数据中初始化点标记数组:

data() {
   return {
       markers: []
   }
},

然后通过计算属性方式从 Vuex 中返回全局咖啡店列表数据:

computed: {
   cafes(){
       return this.$store.getters.getCafes;
   }
},

最后在 methods 中通过 buildMarkers() 方法创建点标记:

methods: {
   // 为所有咖啡店创建点标记
   buildMarkers() {
       // 清空点标记数组
       this.markers = [];

       // 遍历所有咖啡店并为每个咖啡店创建点标记
       for (var i = 0; i < this.cafes.length; i++) {

           // 通过高德地图 API 为每个咖啡店创建点标记并设置经纬度
           var marker = new AMap.Marker({
               position: AMap.LngLat(parseFloat(this.cafes[i].latitude), parseFloat(this.cafes[i].longitude)),
               title: this.cafes[i].name
           });

           // 将每个点标记放到点标记数组中
           this.markers.push(marker);
       }

       // 将所有点标记显示到地图上
       this.map.add(this.markers);
   }
}

此外,我们还要定义一个 clearMarkers() 方法用来在重绘地图时清除地图上的所有点标记:

// 从地图上清理点标记
clearMarkers() {
    // 遍历所有点标记并将其设置为 null 从而从地图上将其清除
    for (var i = 0; i < this.markers.length; i++) {
        this.markers[i].setMap(null);
    }
}

我们还是在 mounted() 中调用这两个方法,以便在初始化地图后可以立即为咖啡店添加点标记:

// 清除并重构点标记
this.clearMarkers();
this.buildMarkers();

最后还需要监听 cafes 数据的变化,一旦有更新,立即清除地图上的所有点标记并重新绘制:

watch: {
    // 一旦 cafes 有更新立即重构地图点标记
    cafes () {
        this.clearMarkers();
        this.buildMarkers();
    }
}

至此,我们已完成了所有代码的编写,运行 npm run dev 重新构建前端资源,刷新 http://roast.test,点击「Cafes」链接,即可看到我们在上一篇教程中新增的咖啡店标记了:

注:完整应用源码位于 nonfu/roastapp

学院君 has written 980 articles

Laravel学院院长,终身学习者

积分:112242 等级:P12 职业:手艺人 城市:杭州

2 条回复

  1. Laragh Laragh says:

    快学完了。。老哥休完十一记得更新哈。。。受益匪浅,辛苦了、

登录后才能进行评论,立即登录?