Featured image of post 行政区划模块实现指南

行政区划模块实现指南

欢迎来到 WebGIS 入门系列的第十一篇文章!在本文中,我们将介绍如何利用高德地图的地理编码服务以及 axios 和 lodash 库来实现行政区划模块。通过本文的学习,您将掌握如何在 WebGIS 应用中实现行政区划的查询和展示功能。

行政区划菜单及面板实现

MapTools 组件中增加一个新菜单,用于实现行政区划定位功能,默认值使用“成都市”(按需设置即可):

<template>
   
  <div class="map-tools">
        <span class="map-tool-item">成都市</span>    
    <span class="map-tool-item" @click="handleSpaceQueryBtnClick"
      >空间查询</span
    >
        <span class="map-tool-item">菜单-3</span>    
    <span class="map-tool-item">菜单-4</span>    
    <span class="map-tool-item">菜单-5</span>    
    <span class="map-tool-item" @click="handleClearScreen">清屏</span>  
  </div>
</template>
// ......

src/components 目录下新建 CityPanel 组件,并将下述代码拷贝至其中:

<template>
   
  <div class="city-panel">
       
    <div class="city-panel-herder">
            <span>当前城市:{{ currentCity }}</span>    
    </div>
       
    <div class="city-panel-content">
           
      <div
        v-for="province in provinceData"
        :key="province.code"
        class="province-item"
      >
                <span>{{ province.name }}</span>        
        <div class="city">
                   
          <div v-for="city in cityData" :key="city.code" class="city-item">
                       
            <span v-if="city.provinceCode === province.code"
              >{{ city.name }}</span
            >
                     
          </div>
                 
        </div>
             
      </div>
         
    </div>
     
  </div>
</template>

<script setup lang="ts">
  import { ref } from "vue"
  import provinceData from "@/data/provinces.json"
  import cityData from "@/data/cities.json"

  const currentCity = ref("四川省成都市")

  console.log(provinceData, cityData)
</script>

<style scoped>
  .city-panel {
    position: absolute;
    top: 60px;
    right: 65px;
    width: 450px;
    height: 400px;
    padding: 0 16px;
    background-color: rgba(255, 255, 255, 0.85);
    box-shadow: 1px 2px 1px rgba(0, 0, 0, 0.15);
    box-sizing: border-box;
  }
  .city-panel-herder {
    height: 48px;
    display: flex;
    align-items: center;
    border-bottom: 1px solid #bfbfbf;
    box-sizing: border-box;
  }
  .city-panel-herder span {
    font-size: 16px;
    font-weight: 600;
  }
  .city-panel-content {
    height: calc(100% - 48px);
    padding: 8px 0;
    box-sizing: border-box;
    overflow: auto;
  }
  .province-item {
    display: flex;
    color: #5f6477;
    font-size: 12px;
    font-weight: 700;
    margin-bottom: 16px;
  }
  .province-item:last-child {
    margin-bottom: 0;
  }
  .province-item > span {
    min-width: 100px;
  }
  .city-item {
    float: left;
    color: #999999;
  }
  .city-item:hover {
    color: #4096ff;
  }
  .city-item > span {
    display: inline-block;
    margin-right: 16px;
    cursor: pointer;
  }
</style>

CityPanel 组件引入至 MapView 组件,在浏览器可看到新建的行政区划组件界面:

行政区划模块

行政区划跳转逻辑实现

预期实现效果:点击各个城市名称,地图中心点跳转至相应城市。 在 CityPanel 组件中的 city-item 元素内的 span 标签上绑定 click 事件,主要实现更新行政区划面板中当前城市名称、实现地图中心点跳转,代码如下:

<template>
    // ......          
  <div v-for="city in cityData" :key="city.code" class="city-item">
               
    <span
      v-if="city.provinceCode === province.code"
      @click="handleCityBtnClick(province, city)"
      >{{ city.name }}</span
    >
             
  </div>
    // ......
</template>

<script setup lang="ts">
  // ......
  import lodash from "lodash"
  import axios from "axios"
  import { useMapViewStore, useCityPanelStore } from "@/stores/counter"
  import { openMessage } from "@/libs/utils"
  import type { MapViewData } from "@/interface/index"

  const mapViewStore = useMapViewStore()
  const cityPanelStore = useCityPanelStore()

  // ......

  function handleCityBtnClick(
    province: {
      code: string
      name: string
    },
    city: { code: string; name: string; provinceCode: string }
  ) {
    const mapView = mapViewStore.mapView as MapViewData

    currentCity.value = `${province.name}${city.name}`
    cityPanelStore.setCityPanelCity(city.name)

    axios
      .get("https://restapi.amap.com/v3/geocode/geo", {
        params: {
          key: "你的高德地图 Web 服务 API Key",
          address: `${province.name}${city.name}`,
        },
      })
      .then((res) => {
        const location = lodash
          .get(res, "data.geocodes[0].location", "")
          .split(",")
        mapView.goTo({
          center: [Number(location[0]), Number(location[1])],
          zoom: 10,
        })
      })
      .catch((err) => {
        console.error(err)
        openMessage("网络错误,请联系管理员", "error")
      })
  }
</script>

上述代码中使用到了两个库:lodashaxios,前者是简化 js 代码逻辑,类似于一个 js 工具库,后者是用于发送网络请求。针对这两个库,如果有不了解的建议去各自官网学一学基础知识即可。 除此之外,为了得到各个城市的经纬度坐标值,此处使用了高德地图的地理编码接口,同理,如果有不了解高德地图 API 的也建议去官网学一学基础知识。 最后,我们点击各个城市名时,除了更新 state 之外,还更新了 store 中的数据,所以我们在 store 中也存放了两个变量信息,主要控制行政区划面板显示/隐藏以及存放当前选中的城市名称:

export const useCityPanelStore = defineStore("cityPanel", () => {
  const cityPanel = ref({
    visible: false,
    city: "成都市",
  })
  function setCityPanelVisible(val: boolean) {
    cityPanel.value.visible = val
  }
  function setCityPanelCity(val: string) {
    cityPanel.value.city = val
  }

  return { cityPanel, setCityPanelVisible, setCityPanelCity }
})

然后回到 MapTools 组件中,在行政区划菜单上面绑定 click 事件,主要更新面板的显示/隐藏状态,以及显示当前存放在 store 中的城市名称:

<template>
  <div class="map-tools">
    <span class="map-tool-item" @click="handleXZQHBtnClick">{{
      cityPanelStore.cityPanel.city
    }}</span>
    // ......
  </div>
</template>

<script setup lang="ts">
import { useMapViewStore, useCityPanelStore } from '@/stores/counter'
// ......
 
const mapViewStore = useMapViewStore()
const cityPanelStore = useCityPanelStore()

// ......

function handleXZQHBtnClick() {
  cityPanelStore.setCityPanelVisible(!cityPanelStore.cityPanel.visible)
}

同理,在 CityPanel 组件中也要根据 store 中面板的显示/隐藏状态值更新此面板的显示和隐藏:

<template>
   
  <div class="city-panel" v-show="cityPanelStore.cityPanel.visible">
        // ......  
  </div>
</template>

此时在界面就可以看到行政区划完整的功能了:

行政区划模块

小作业:代码优化

虽然按照上述操作完成了行政区划模块的功能,但是有部分代码可以进行优化,例如点击各个直辖区时,菜单上面展示的是“直辖区”三个字的文案,预期是要展示直辖市名称;保存当前选中的城市时,其实不用 statestore 两份数据,只用 store 就可以……

结语

通过本文的学习,您已经掌握了如何利用高德地图的地理编码服务以及 axios 和 lodash 库来实现行政区划模块。行政区划查询是 WebGIS 应用中常见的功能之一,能够帮助用户快速获取感兴趣区域的行政区划信息。 希望本文能够为您在行政区划模块的实现方面提供一定的帮助,并且启发您进一步探索 WebGIS 开发的世界。祝您在 WebGIS 开发的旅程中取得成功!