前言

今天要实现的是行政区边界绘制
我们先说一下需求
当用户在页面上输入一个地点之后点击搜索,我们的地图会显示行政区(国,区,市等)的边界,这听起来很简单,确实如果在一个页面上同时编好地图,搜索框确实很简单但是如果我们使用vue则不然
在vue上我们把search组件和地图组件分成了两个单独的组件然后又放在一个vue页面中,这就需要我们进行组件之间的数据传输,数据监测这些手段!

原理

使用高德地图的AMap.DistrictSearch进行搜索后获取区域边界的坐标值,然后将坐标值提取成数组,最后进行绘制

基础

  1. 高德地图AMap.DistrictSearch了解
  2. 高德地图placeSearch周边搜索
  3. es6语法
  4. eslint变量全局设置
  5. 如果有疑问一定要看前面几篇文章因为都是连贯起来的

实现步骤

1.eslint设置AMap为全局变量放置报错

打开vue项目中的eslintrc.js
在这里插入图片描述
添加如下信息

globals: {
    AMap: true
  }

在这里插入图片描述

2.Search.vue传输给MapContainer.vue数据然后进行监测

eventBus.js

import Vue from 'vue'
//兄弟组件之间进行通行
export default new Vue()

2.1Search.vue上进行传输input输入框的内容以及input输入框的id

<script>
import bus from '@/eventBus/eventBus.js'
export default {
  data() {
    return {
      search_id: 'searchId',
      input: ''
    }
  },

  methods: {
  //传输入框
    sendMsg() {
      bus.$emit('share', this.input)
    },
    //传id
    sendId() {
      bus.$emit('share_id', this.search_id)
    }
  },
  mounted() {
    this.sendId()
  }
}
</script>

2.2在MapContainer.vue上接收构建监测

当watch监测到输入框的值改变发送过来就会调用drawBounds(newValue)函数

data() {
    return {
      map: null,
      //接收Search组件传输input的id
      autoOptions: {
        input: ''
      },
      auto: null,
      placeSearch: null,
      //接收Search组件传输input输入框的值
      searchPlaceInput: '',
      district: null,
      polygons: []
    }
  },

  created() {
    //Search组件传输input的id
    bus.$on('share_id', val => {
      this.autoOptions.input = val
    }),
      //Search组件传输input输入框的值
      bus.$on('share', val => {
        this.searchPlaceInput = val
      })
  },
  watch: {
    // 点击搜索按钮后传值的poi搜索
    searchPlaceInput(newValue) {
      if (newValue != null) {
        this.placeSearch.search(newValue)
        this.map.setZoom(16, true, 1)
        this.drawBounds(newValue)
      }
    }
  }

3.编写drawBounds(newValue)边界绘制函数

methods:{
	// 行政区区域划分
    drawBounds(newValue) {
      //加载行政区划插件
      if (!this.district) {
        //实例化DistrictSearch
        var opts = {
          subdistrict: 0, //获取边界不需要返回下级行政区
          extensions: 'all', //返回行政区边界坐标组等具体信息
          level: 'district' //查询行政级别为 市
        }

        this.map.plugin(['AMap.DistrictSearch'], () => {
          this.district = new AMap.DistrictSearch(opts)
        })
        // this.district = new AMap.DistrictSearch(opts)
      }
      //行政区查询
      this.district.search(newValue, (status, result) => {
        if (this.polygons != null) {
          this.map.remove(this.polygons) //清除上次结果
          this.polygons = []
        }
        var bounds = result.districtList[0].boundaries
        if (bounds) {
          for (var i = 0, l = bounds.length; i < l; i++) {
            //生成行政区划polygon
            var polygon = new AMap.Polygon({
              strokeWeight: 1,
              path: bounds[i],
              fillOpacity: 0.4,
              fillColor: '#80d8ff',
              strokeColor: '#0091ea'
            })
            this.polygons.push(polygon)
          }
        }
        this.map.add(this.polygons)
        this.map.setFitView(this.polygons) //视口自适应
      })
    }
}

官方代码

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>行政区边界查询</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css"/> 
    <style>
        html,body,#container{
            margin:0;
            height:100%;
        }
        .input-item-text{
            width:7rem;
        }
    </style>
</head>
<body>
<div id="container"></div>
<div class="input-card">
    <label style='color:grey'>行政区边界查询</label>
    <div class="input-item">
            <div class="input-item-prepend">
                <span class="input-item-text" >行政级别</span>
            </div>
            <select id="level">
                <option value="district">district</option>
                <option value="city">city</option>
                <option value="province">province</option>
            </select>
            
    </div>
    <div class="input-item">
            <div class="input-item-prepend">
                <span class="input-item-text" >名称/adcode</span>
            </div>
            <input id='district' type="text" value='朝阳区'>
            
    </div>
    <input id="draw" type="button" class="btn" value="查询" />
</div>
<script type="text/javascript" src="//webapi.amap.com/maps?v=2.0&key=您申请的key值&plugin=AMap.DistrictSearch"></script>
<script type="text/javascript">
    //初始化地图对象,加载地图
    var map = new AMap.Map("container", {
        center: [116.397428, 39.90923],//地图中心点
        zoom: 10 //地图显示的缩放级别
    });
    
    var district = null;
    var polygons=[];
    function drawBounds() {
        //加载行政区划插件
        if(!district){
            //实例化DistrictSearch
            var opts = {
                subdistrict: 0,   //获取边界不需要返回下级行政区
                extensions: 'all',  //返回行政区边界坐标组等具体信息
                level: 'district'  //查询行政级别为 市
            };
            district = new AMap.DistrictSearch(opts);
        }
        //行政区查询
        district.setLevel(document.getElementById('level').value)
        district.search(document.getElementById('district').value, function(status, result) {
            map.remove(polygons)//清除上次结果
            polygons = [];
            var bounds = result.districtList[0].boundaries;
            if (bounds) {
                for (var i = 0, l = bounds.length; i < l; i++) {
                    //生成行政区划polygon
                    var polygon = new AMap.Polygon({
                        strokeWeight: 1,
                        path: bounds[i],
                        fillOpacity: 0.4,
                        fillColor: '#80d8ff',
                        strokeColor: '#0091ea'
                    });
                    polygons.push(polygon);
                }
            }
            map.add(polygons)
            map.setFitView(polygons);//视口自适应
        });
    }
    drawBounds();
    document.getElementById('draw').onclick = drawBounds;
    document.getElementById('district').onkeydown = function(e) {
        if (e.keyCode === 13) {
            drawBounds();
            return false;
        }
        return true;
    };
</script>
</body>
</html>

使用官方代码会报错this is undefined

这是因为官方使用的函数是

function(){}

在这里插入图片描述

解决

这也是报错的原因,我们要把这个回调函数改成es6语法下的箭头函数就不会报错了

()=>{}

在这里插入图片描述

完整代码(MapContainer.vue)

<script>
import bus from '@/eventBus/eventBus.js'
import AMapLoader from '@amap/amap-jsapi-loader'

export default {
  data() {
    return {
      map: null,
      //接收Search组件传输input的idy
      autoOptions: {
        input: ''
      },
      auto: null,
      placeSearch: null,
      //接收Search组件传输input输入框的值
      searchPlaceInput: '',
      district: null,
      polygons: []
    }
  },

  created() {
    //Search组件传输input的id
    bus.$on('share_id', val => {
      this.autoOptions.input = val
    }),
      //Search组件传输input输入框的值
      bus.$on('share', val => {
        this.searchPlaceInput = val
      })
  },
  methods: {
    initMap() {
      AMapLoader.load({
        key: '2c1c4affeb410923990fec54c5af721a', // 申请好的Web端开发者Key,首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: ['AMap.DistrictSearch', 'AMap.ToolBar', 'AMap.Scale', 'AMap.HawkEye', 'AMap.MapType', 'AMap.Geolocation', 'AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then(AMap => {
          this.map = new AMap.Map('container', {
            resizeEnable: true,
            //设置地图容器id
            viewMode: '3D', //是否为3D地图模式
            zoom: 14, //初始化地图级别
            center: [121.473667, 31.230525] //初始化地图中心点位置
          })
          this.map.addControl(new AMap.Scale())
          this.map.addControl(new AMap.ToolBar())
          this.map.addControl(new AMap.HawkEye())
          this.map.addControl(new AMap.MapType())
          this.map.addControl(new AMap.Geolocation())
          this.auto = new AMap.AutoComplete(this.autoOptions)
          // 绑定搜索地图
          this.placeSearch = new AMap.PlaceSearch({
            map: this.map
          }) //构造地点查询类
          this.auto.on('select', this.select)
        })
        .catch(e => {
          console.log(e)
        })
    },
    //poi搜索
    select(e) {
      this.placeSearch.setCity(e.poi.adcode)
      this.placeSearch.search(e.poi.name) //关键字查询查询
      this.map.setCenter([e.poi.location.lng, e.poi.location.lat])
      this.map.setZoom(16, true, 1)
      this.drawBounds(e.poi.name)
    },

    // 行政区区域划分
    drawBounds(newValue) {
      //加载行政区划插件
      if (!this.district) {
        //实例化DistrictSearch
        var opts = {
          subdistrict: 0, //获取边界不需要返回下级行政区
          extensions: 'all', //返回行政区边界坐标组等具体信息
          level: 'district' //查询行政级别为 市
        }

        this.map.plugin(['AMap.DistrictSearch'], () => {
          this.district = new AMap.DistrictSearch(opts)
        })
        // this.district = new AMap.DistrictSearch(opts)
      }
      //行政区查询
      this.district.search(newValue, (status, result) => {
        if (this.polygons != null) {
          this.map.remove(this.polygons) //清除上次结果
          this.polygons = []
        }
        var bounds = result.districtList[0].boundaries
        if (bounds) {
          for (var i = 0, l = bounds.length; i < l; i++) {
            //生成行政区划polygon
            var polygon = new AMap.Polygon({
              strokeWeight: 1,
              path: bounds[i],
              fillOpacity: 0.4,
              fillColor: '#80d8ff',
              strokeColor: '#0091ea'
            })
            this.polygons.push(polygon)
          }
        }
        this.map.add(this.polygons)
        this.map.setFitView(this.polygons) //视口自适应
      })
    }
  },
  mounted() {
    //DOM初始化完成进行地图初始化
    this.initMap()
    // this.drawBounds()
  },
  watch: {
    // 点击搜索按钮后传值的poi搜索
    searchPlaceInput(newValue) {
      if (newValue != null) {
        this.placeSearch.search(newValue)
        this.map.setZoom(16, true, 1)
        this.drawBounds(newValue)
      }
    }
  }
}
</script>

结果展示

在这里插入图片描述

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐