前言:
当我们需要用到高德地图的时候,周边搜索和路线规划是常见的功能,我们也常常在旅游官网中见到他们的身影,因此接下来在Vue项目中来简单的演示一下这两个功能吧。

1.引入

可以直接在public/index.html的头部添加,记住需要放到</body>的前面。

<body>
//...其他代码
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值"></script>
</body>

2.周边搜索

1.在template里面添加div标签作为地图容器,同时为该div指定id属性。

<template>
  <div class="container">
    <div class="Map">
      <div class="Map" id="Map"></div>
     </div>
  </div>
</template>

2.设定地图的高度和宽度。

  #Map {
      width: 650px;
      height: 350px;
      margin-top: 10px;
   }

3.去高德申请key https://lbs.amap.com/api/webservice/guide/create-project/get-key

4.寻找官网周边搜索Api https://lbs.amap.com/api/webservice/guide/api/search

image.png
封装一个简单的axios文件,新建src/request/axios.js文件。

import axios from "axios";
export const axiosMap = (postUrl, method, data) => {
  if (method === "get") {
    let params = data;
    return axios({
      url: `https://restapi.amap.com/${postUrl}`,
      method: method,
      params
    })
      .then(res => res)
      .catch(err => err);
  }
};
<script>
//个人自己封装的axios
import { axiosMap} from "@/request/axios.js";
export default {
  data() {
    return {
      pois: [], //周边搜索的数据
 
    };
  },
  async mounted() {
    // 获取数据
    await this.searchAround('风景');
  },
  methods: {
    //创建地图
    createMap() {
      this.map = new AMap.Map("Map", {
        zoom: 13,
      });
    },
    // 周边搜索
   searchAround(types) {
      let data = {
        key: "您申请的key值",
        location: "113.40135612,23.0855435",//搜索中心的坐标点
        types: types,
      };
      axiosMap("v3/place/around", "get", data).then((res) => {
        console.log(res);
        // 创建地图
        this.pois = res.data.pois;//周边搜索的数据
        this.createMap();
      });
    },
  },
};
</script>

看下接口返回

image.png

很好,接下来就是把返回的信息展示出来。我曾经看到有一旅游官网里面的酒店详情页面,会将附近的景点坐标使用tab导航来展示,并且在地图上添加对应的marker坐标点,再给坐标点加上鼠标 Hover 事件。下面我们来实现一下。

html这里使用element的el-tabs,遍历pois,并且加上mouseover事件。

      <div class="MapTab">
        <el-tabs v-model="activeName" @tab-click="handleClick" class="el-tabs">
          <el-tab-pane
            :label="tab.label"
            :name="tab.name"
            v-for="(tab, tabIndex) in tabList"
            :key="tabIndex"
          >
            <div class="listData">
              <div
                class="list"
                v-for="item in pois"
                :key="item.id"
                @mouseover="showPoi(item.id)"
                @click="choosePoi(item)"
              >
                <span class="name">{{ item.name }}</span>
                <span class="distance"
                  >{{ (Math.round(item.distance) / 1000).toFixed(2) }}公里</span
                >
              </div>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>

tab标签选项有风景、餐厅、停车场、酒店,当然也可以添加其他的label。 这里的label作为 searchAround(types)的参数。

  data() {
    return {
      activeName: "scenery",
      pois: [], //周边搜索的数据
      markers: [], //存储点标记
      //自定义tabList数组
      tabList: [
        { label: "风景", name: "scenery" },
        { label: "餐厅", name: "restaurant" },
        { label: "停车场", name: "park" },
        { label: "酒店", name: "hotel" },
      ], 
    };
  },
  // 生成点标记
    setMarkers() {
      // 遍历 pois 列表, 让每个 poi 生成一个 marker
      this.markers = this.pois.map((poi, i) => {
        var marker = new AMap.Marker({
          title: poi.name,//周边地点名称
          position: poi.location.split(","),//周边地点坐标
          content: `<span class="marker">${i + 1}</span>`,//标记覆盖物的内容
          extData: poi.id,//将poi的id作为marker的id
        });
        // 设置每个点标记鼠标Hover事件
        // 传入当前的 poiId, 进行居中
        marker.on("mouseover", () => {
          return this.showMarker(poi.id);
        });
        return marker;
      });
      // 使用通用函数,将整个地图的覆盖物清理掉
      this.map.clearMap();
       //添加点标记
      this.map.add(this.markers);
      // 将地图的视图设为合适的大小
      this.map.setFitView();
    },
      // 控制坐标点,找到需要居中的标记
    showMarker(poiId) {
      // 外面传入 poiId
      this.markers.forEach((marker) => {
        // 判断标记的额外信息是否等于传进来的poiId
        // console.log(marker.getExtData());
        if (marker.getExtData() == poiId) {
          // 将匹配点置顶(重叠的情况)
          marker.setTop(true);
          //显示一个提示窗
          this.showTips(marker);
          // 设置地图以这个点居中
          this.map.setCenter(marker.getPosition());
        }
      });
    },
    // 居中时显示一个窗口
    showTips(marker) {
      //显示一个提示窗
      const infoWindow = new AMap.InfoWindow({
        content: `<span style="font-size: 12px;color: #333">${marker.getTitle()}</span>`,
        offset: new AMap.Pixel(0, -32),//偏移量
      });
      infoWindow.open(this.map, marker.getPosition());
    },
    handleClick(tab, event) {
      //选中不同的标签页的时候把tab.label传到searchAround()函数调用接口。
      this.searchAround(tab.label);
    },

相关的css代码省略。

很好,接下来看看页面的效果。

高德地图周边搜索.gif
好了,周边搜索效果已经出来,那么我们能不能再原有的基础上,使两个不同的景点像导航那样把路线画出来。接下来就要用到高德地图的路线规划。

3.路线规划

我们先把单独的路线规划实现出来。

查看高德官网的API https://lbs.amap.com/api/webservice/guide/api/direction

image.png

<template>
  <div class="container">
    <div class="mapDetail">
      <div class="Map" id="Map"></div>
      <!-- 路线节点 panel-->
      <div id="panel"></div>
    </div>
  </div>
</template>
<script>
import { axiosMap, baseUrl } from "@/request/axios.js";
export default {
  data() {
    return {};
  },
  async mounted() {
    // 获取点数据
    await this.pathPlanning();
    // 创建地图
    this.createMap();
  },
  methods: {
    //创建地图
    createMap() {
      var map = new AMap.Map("Map", {
        zoom: 13,
        resizeEnable: true,
        center: [113.40135612,23.0855435], //地图中心点
      });
      // 创建完地图, 就将路线规划出来。
      this.setWarking(map);
    },
    //请求高德步行路径规划接口
    pathPlanning(types) {
      let data = {
        key: "您申请的key值",
        origin: "113.40135612,23.0855435", //出发点
        destination: "113.81135612,23.1355435", //目标点
      };
      //步行
      axiosMap("v3/direction/walking", "get", data).then((res) => {
        //创建地图
        this.createMap();
      });
    },
    //在地图上加载路线
    setWarking(map) {
      //步行导航
      var walking = new AMap.Walking({
        map,
        panel: "panel", // <div id="panel"></div>  路线节点的id
      });
      //根据起终点坐标规划步行路线
      walking.search(
        [113.40135612, 23.0855435], //出发点
        [113.81135612, 23.1355435], //目标点
        function (status, result) {
          console.log(status, result);
          // result即是对应的步行路线数据信息,相关数据结构文档请参考  https://lbs.amap.com/api/javascript-api/reference/route-search#m_WalkingResult
          if (status === "complete") {
            console.log("绘制步行路线完成");
          } else {
            console.log("步行路线数据查询失败" + result);
          }
        }
      );
    },
  },
};
</script>
<style lang='less' scoped>
//样式省略
</style>

看看效果:

image.png

很明显,如果采取起点到终点有点远,步行居然要12个小时。

当然,官网上还给出了其他的路线规划。

image.png

  //请求高德公交路径规划接口
    pathPlanning(types) {
      let data = {
        key: "您申请的key值",
        origin: "113.40135612,23.0855435", //出发点
        destination: "113.81135612,23.1355435", //目标点
        city: "440100", //广州市的adcode
      };
      axiosMap("v3/direction/transit/integrated", "get", data).then((res) => {
        //创建地图
        this.createMap();
      });
    },
    //在地图上加载路线
    setWarking(map) {
      var transOptions = {
        map: map,
        city: "广州市",
        panel: "panel",
        policy: "AMap.TransferPolicy.LEAST_TIME",//最短时间
      };
      //构造公交换乘类
      var transfer = new AMap.Transfer(transOptions);
      //根据起、终点坐标查询公交换乘路线
      transfer.search(
        new AMap.LngLat(113.40135612, 23.0855435),
        new AMap.LngLat(113.81135612, 23.1355435),
        function (status, result) {
          // result即是对应的公交路线数据信息,相关数据结构文档请参考  https://lbs.amap.com/api/javascript-api/reference/route-search#m_TransferResult
          if (status === "complete") {
            console.log("绘制公交路线完成");
          } else {
            console.log("公交路线数据查询失败" + result);
          }
        }
      );
    },

image.png

很好,时间缩短了。当然,也可以使用驾车路线规划,这里就不做演示。

4.功能合并

为了功能更加完善,所以我们模仿平时使用高德地图的情景。

  • 首先在输入框输入一个地址,比如学校。搜索,得到学校列表,选择其中一所学校。
  • 根据这所学校,以此为中心坐标,搜索周边景点。
  • 选择其中一处景点,规划学校到景点的路线。

以下为全部代码:

<template>
  <div class="container">
    <div class="search">
      <el-form ref="form" :model="form" label-width="80px">
        <div class="line">
          <el-form-item label="搜索地点">
            <el-input
              v-model="form.location"
              class="inputWidth"
              placeholder="搜索地点"
            ></el-input>
          </el-form-item>
          <el-form-item label="选择地点">
            <el-select
              v-model="form.chooseLocation"
              placeholder="选择地点"
              class="inputWidth"
              clearable
              filterable
              value-key="id"
              @change="changeLocation"
            >
              <el-option
                v-for="item in tips"
                :label="item.name"
                :value="item"
                :key="item.id"
              >
              </el-option>
            </el-select>
          </el-form-item>
        </div>
        <div class="line">
          <el-form-item label="起始地点">
            <el-input
              v-model="form.origin"
              class="inputWidth"
              placeholder="起始地点"
            ></el-input>
          </el-form-item>
          <el-form-item label="起始坐标">
            <el-input
              v-model="form.coordinate"
              class="inputWidth"
              placeholder="起始坐标"
            ></el-input>
          </el-form-item>
        </div>
        <div class="line">
          <el-form-item label="目标地点">
            <el-input
              v-model="form.targetLocation"
              class="inputWidth"
              placeholder="目标地点"
            ></el-input>
          </el-form-item>
          <el-form-item label="目标坐标">
            <el-input
              v-model="form.targetCoordinate"
              class="inputWidth"
              placeholder="目标坐标"
            ></el-input>
          </el-form-item>
        </div>
        <div class="line">
          <el-button type="primary" @click="searchLocation" class="Btn"
            >搜索地点</el-button
          >
          <el-button type="primary" @click="searchAround('风景')" class="Btn"
            >搜索周边</el-button
          >
          <el-button type="primary" @click="pathPlanning" class="Btn"
            >规划路线</el-button
          >
          <el-button type="primary" @click="clearData" class="Btn"
            >清空</el-button
          >
        </div>
      </el-form>
    </div>
    <div class="mapDetail">
      <div class="Map" id="Map"></div>
      <div id="panel"></div>
      <div class="MapTab">
        <el-tabs v-model="activeName" @tab-click="handleClick" class="el-tabs">
          <el-tab-pane
            :label="tab.label"
            :name="tab.name"
            v-for="(tab, tabIndex) in tabList"
            :key="tabIndex"
          >
            <div class="listData">
              <div
                class="list"
                v-for="item in pois"
                :key="item.id"
                @click="choosePoi(item)"
              >
                <span class="name">{{ item.name }}</span>
                <span class="distance"
                  >{{ (Math.round(item.distance) / 1000).toFixed(2) }}公里</span
                >
              </div>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
  </div>
</template>
<script>
import { axiosMap, baseUrl } from "@/request/axios.js";
export default {
  data() {
    return {
      activeName: "scenery",
      pois: [], //周边搜索的数据
      markers: [], //存储点标记
      map: null, //生成的地图
      tips: [], //搜索的地址列表
      tabList: [
        { label: "风景", name: "scenery" },
        { label: "餐厅", name: "restaurant" },
        { label: "停车场", name: "park" },
        { label: "酒店", name: "hotel" },
      ],
      form: {
        location: "", //搜索地点
        chooseLocation: null, //搜索地点坐标
        coordinate: "", //起始地点
        origin: "", //起始地点
        targetCoordinate: "", //目标坐标
        targetLocation: "", //目标地点
      },
    };
  },
  mounted() {
    // 创建地图
    this.createMap();
  },
  methods: {
    //选择初始坐标
    changeLocation(val) {
      this.form.origin = val.name; //起始地点
      this.form.coordinate = val.location; //起始坐标
      // 使用通用函数,将整个地图的覆盖物清理掉
      this.map.clearMap();
      let marker = new AMap.Marker({
        title: val.name, //地点名称
        position: val.location.split(","), //地点坐标
        content: `<span class="marker">${val.name}</span>`, //标记覆盖物的内容
      });
      //添加点标记
      this.map.add(marker);
      // 设置地图以这个点居中
      this.map.setCenter(val.location.split(","));
      // 将地图的视图设为合适的大小
      this.map.setFitView();
    },
    //选择景点
    choosePoi(item) {
      this.form.targetLocation = item.name; //目标地点
      this.form.targetCoordinate = item.location; //目标坐标
    },
    //创建地图
    createMap() {
      this.map = new AMap.Map("Map", {
        zoom: 13,
      });
    },
    //根据type生成标记或路线
    setMap(type) {
      //根据type显示不同地图
      if (type == "Marker") {
        //遍历 pois 列表, 每个地点都创建一个 marker 放到地图上
        this.setMarkers();
      } else if (type == "panel") {
        //规划步行路线
        this.setWarking();
      }
    },
    //搜索地点
    searchLocation() {
      let data = {
        key: "您申请的key值",
        location: "113.40135612,23.0855435", //以此坐标搜索周边
        keywords: this.form.location, //关键字
      };
      axiosMap("v3/assistant/inputtips", "get", data).then((res) => {
        this.tips = res.data.tips; //将请求所得的标记储存起来
      });
    },
    // 周边搜索
    searchAround(types) {
      let data = {
        key: "您申请的key值",
        location: this.form.chooseLocation.location, //以此坐标搜索周边
        types, //默认为风景
      };
      axiosMap("v3/place/around", "get", data).then((res) => {
        this.pois = res.data.pois; //将请求所得的标记储存起来
        //生成标记
        this.setMap("Marker");
      });
    },
    setWarking() {
      //步行导航
      var walking = new AMap.Walking({
        map: this.map,
        panel: "panel",
      });
      //根据起终点坐标规划步行路线
      walking.search(
        this.form.coordinate.split(","), //起点和终点坐标为数组
        this.form.targetCoordinate.split(","),
        (status, result) => {
          console.log(status, result);
          // result即是对应的步行路线数据信息,相关数据结构文档请参考  https://lbs.amap.com/api/javascript-api/reference/route-search#m_WalkingResult
          if (status === "complete") {
            // log.success("绘制步行路线完成");
          } else {
            // log.error("步行路线数据查询失败" + result);
          }
        }
      );
    },
    //路线规划
    pathPlanning() {
      let data = {
        key: "您申请的key值",
        origin: this.form.coordinate, //出发点
        destination: this.form.targetCoordinate, //目标点
      };
      axiosMap("v3/direction/walking", "get", data).then((res) => {
        // 使用通用函数,将整个地图的覆盖物清理掉
        this.map.clearMap();
        //生成路线
        this.setMap("panel");
      });
    },
    // 生成点标记
    setMarkers() {
      // 遍历 pois 列表, 让每个 poi 生成一个 marker
      this.markers = this.pois.map((poi, i) => {
        var marker = new AMap.Marker({
          title: poi.name, //周边地点名称
          position: poi.location.split(","), //周边地点坐标
          content: `<span class="marker">${i + 1}</span>`, //标记覆盖物的内容
          extData: poi.id, //将poi的id作为marker的id
        });
        // 设置每个点标记鼠标Hover事件
        // 传入当前的 poiId, 进行居中
        marker.on("mouseover", () => {
          return this.showMarker(poi.id);
        });
        return marker;
      });
      // 使用通用函数,将整个地图的覆盖物清理掉
      this.map.clearMap();
      //添加点标记
      this.map.add(this.markers);
      // 将地图的视图设为合适的大小
      this.map.setFitView();
    },
    // 控制坐标点,找到需要居中的标记
    showMarker(poiId) {
      // 外面传入 poiId
      this.markers.forEach((marker) => {
        // 判断标记的额外信息是否等于传进来的poiId
        // console.log(marker.getExtData());
        if (marker.getExtData() == poiId) {
          // 将匹配点置顶(重叠的情况)
          marker.setTop(true);
          //显示一个提示窗
          this.showTips(marker);
          // 设置地图以这个点居中
          this.map.setCenter(marker.getPosition());
        }
      });
    },
    // 居中时显示一个窗口
    showTips(marker) {
      //显示一个提示窗
      const infoWindow = new AMap.InfoWindow({
        content: `<span style="font-size: 12px;color: #333">${marker.getTitle()}</span>`,
        offset: new AMap.Pixel(0, -32), //偏移量
      });
      infoWindow.open(this.map, marker.getPosition());
    },
    handleClick(tab, event) {
      //选中不同的标签页的时候把tab.label传到searchAround()函数调用接口。
      this.searchAround(tab.label);
    },
    //清空数据
    clearData() {
      this.form = {
        location: "", //搜索地点
        chooseLocation: null, //搜索地点坐标
        coordinate: "", //起始地点
        origin: "", //起始地点
        targetCoordinate: "", //目标坐标
        targetLocation: "", //目标地点
      };
      this.pois = []; //周边搜索的数据
      this.tips = []; //搜索的地址列表
    },
  },
};
</script>

样式代码就不展示了,虽然页面简陋,但是研究起来还是蛮有意思的。最后展示一下效果图。

高德地图功能合并.gif
原文地址:https://juejin.cn/post/6982881752423350308

Logo

前往低代码交流专区

更多推荐