Bootstrap

vue-实现高德地图-省级行政区地块显示+悬浮显示+标签显示+省市级切换

在这里插入图片描述

<template>
  <div>
    <div id="container" />
    <div @click="showFn">显示</div>
    <div @click="removeFn">移除</div>
  </div>
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import chinaData from './provincialData/中华人民共和国.json'
export default {
  data() {
    return {
      map: null,
      infoWindow: null,
      markers: [],
      provincPolygonList: []
    }
  },
  async mounted() {
    await this.initMap()
    // 初始完地图后,开始绘制
    await this.setUpPlotsFn(chinaData)
  },
  methods: {
    /** 1. 初始化地图 **/
    initMap() {
      return new Promise((resolve) => {
        window._AMapSecurityConfig = {
          securityJsCode: '你的安全密钥' // 自2021年12月02日升级后, key与安全密钥必须一起使用, 否则可能会出现一些API无法使用,如 DistrictSearch
        }
        AMapLoader.load({
          key: '你的安全密钥key', // 首次调用 load 时必填
          version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
          plugins: [
            'AMap.DistrictSearch', // 配置行政区查询服务
            'AMap.GeoJSON' // 配置行政区查询服务
          ] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
        })
          .then((AMap) => {
            this.map = new AMap.Map('container', {
              center: [116.30946, 39.937629],
              zoom: 3
            })
            this.map.on('complete', () => {
              resolve()
            })
          })
          .catch((e) => {
            console.log(e)
          })
      })
    },

    // 设置地块
    setUpPlotsFn(featuresObj) {
      const { features } = featuresObj
      features.forEach((item) => {
        this.addGeoJsonFn(item)
      })
      this.map.add(this.provincPolygonList)
      this.map.add(this.markers)
      // 地图自适应
      this.map.setFitView()
    },
    // GeoJson数据进行解析
    addGeoJsonFn(feature) {
      const geoJSON = {
        type: 'FeatureCollection',
        features: [feature]
      }
      this.map.plugin('AMap.Geocoder', () => {
        const polygon = new window.AMap.GeoJSON({
          geoJSON: geoJSON,
          getPolygon: function(geojson, lnglats) {
            // 将解析出来的面 进行绘制
            return new window.AMap.Polygon({
              path: lnglats,
              fillOpacity: 0.4,
              fillColor: '#80d8ff',
              strokeColor: '#08B2BD',
              strokeWeight: 1,
              map: this.map
            })
          }
        })
        const { name, centroid } = feature.properties
        console.log('🚀 ~ file: MapConnentNewLast.vue:89 ~ this.map.plugin ~  feature.properties:', feature.properties)
        polygon.on('mouseover', (e) => {
          // 鼠标移入更改样式
          polygon.setOptions({
            fillOpacity: 0.7,
            fillColor: '#08B2BD'
          })
          const info = []
          info.push(
            `<div style="font-size: 12px; background-color: #fff;padding: 10px; border-radius: 10px;"><div style="font-weight: 700;">${name}</div>`
          )
          info.push(
            '<div style="display: flex; justify-content: space-between;align-items: center;padding: 4px 0;"><span style="color:#666;padding-right: 10px;">聚合资源总量</span> <span style="font-weight: 700;">100MW</span></div>'
          )
          info.push(
            '<div style="display: flex; justify-content: space-between;align-items: center;padding: 4px 0;"><span style="color:#666;">充电站</span> <span style="font-weight: 700;">100座</span></div>'
          )
          info.push(
            '<div style="display: flex;justify-content: space-between;align-items: center;padding: 4px 0;"><span style="color:#666;">换电站</span> <span style="font-weight: 700;">100座</span></div>'
          )
          info.push(
            '<div style="display: flex;justify-content: space-between;align-items: center;padding: 4px 0;"><span style="color:#666;">光伏</span> <span style="font-weight: 700;">100MW</span></div>'
          )
          info.push(
            '<div style="display: flex; justify-content: space-between;align-items: center;padding: 4px 0;"><span style="color:#666;">储能</span> <span style="font-weight: 700;">100MWH</span></div></div>'
          )
          this.infoWindow = new window.AMap.InfoWindow({
            isCustom: true, // 使用自定义窗体
            content: info.join(''),
            offset: new window.AMap.Pixel(0, -30)
          })
          // 获取点击的位置信息
          const lnglat = e.lnglat
          // 在点击的位置上显示信息窗体
          this.infoWindow.open(this.map, lnglat)
        })

        polygon.on('mouseout', () => {
          // 鼠标移出恢复样式
          this.infoWindow.close()
          polygon.setOptions({
            fillOpacity: 0.5,
            fillColor: '#80d8ff'
          })
        })

        this.provincPolygonList.push(polygon)

        const center = this.$turf.centroid(geoJSON).geometry.coordinates
        console.log('🚀 ~ file: MapConnentNewLast.vue:138 ~ this.map.plugin ~ center:', center)
        if (name) {
          this.addMarkerList(centroid || center, name)
        }
      })
    },

    addMarkerList(center, item) {
      const markersContent = []
      markersContent.push(`<div style="display: flex;align-items: center;font-size: 10px;border-radius: 4px;">`)
      markersContent.push(
        `<span style="color:#666;background-color: #fff;min-width: 40px;height: 20px;display: flex;align-items: center;justify-content:center">${item}</span>`
      )
      markersContent.push(
        `<span style="color:#fff;background-color: #3AD6C4;min-width: 40px;height: 20px;display: flex;align-items: center;justify-content:center">3213</span>`
      )
      markersContent.push(`</div>`)
      const marker = new window.AMap.Marker({
        position: center, // 标注点位置
        content: markersContent.join(''),
        map: this.map // 将标注点添加到地图上
      })
      this.markers.push(marker)
    },
    // 隐藏
    removeFn() {
      if (this.markers) {
        this.markers.forEach((item) => item.hide())
        this.provincPolygonList.forEach((item) => item.hide(item))
      }
    },
    // 隐藏
    showFn() {
      if (this.markers) {
        this.markers.forEach((item) => item.show())
        this.provincPolygonList.forEach((item) => item.show(item))
      }
    }
  }
}
</script>

<style scoped lang="scss">
#container {
  width: 100%;
  height: 53vh;
}

.infoWindow {
  display: flex;
  flex-direction: column;
  font-size: 10px;

  .title {
    color: #000;
  }

  .info_item {
    display: flex;
    justify-content: space-between;
    align-items: center;

    &:first-child {
      span {
        color: #444;

      }
    }
  }
}

.amap-info-content {
  border-radius: 10px;
}</style>

遇到的问题:

获取地块数据的链接 https://datav.aliyun.com/portal/school/atlas/area_selector
在这里插入图片描述

1. 获取到的地块数据不符合全省的各个地块范围

解决方法:构造多边形的地块数据,能够符合地块显示的格式
获取的文件格式
在这里插入图片描述

    /**
     * GeoJson数据进行解析
     * @param {*} feature 地块
     * @returns {*} polygonObj 解析的地块
     * @returns {*} markerObj 解析的标记
     */
    addGeoJsonFn(feature) {
      const geoJSON = {
        type: 'FeatureCollection',
        features: [feature]
      }
    

2. 自定义标记masker样式修改

*解决方法:需要加 /deep/ 才能生效

    // 添加标识
    addMarkerList(center, name, infoObj, level) {
      const markersContent = [
        `<div class='markers_connent'>`,
        `<span class='markers_connent_left' >${name}</span>`,
        `<span class='${level === 'city' ? 'markers_connent_right_city' : 'markers_connent_right'}'>666</span>`,
        `</div>`
      ]
      const marker = new window.AMap.Marker({
        position: center, // 标注点位置
        content: markersContent.join(''),
        map: this.map // 将标注点添加到地图上
      })
      return marker
    },
/deep/ .markers_connent {
  display: flex;
  align-items: center;
  font-size: 10px;
  border-radius: 4px;

  .markers_connent_left {
    color: #666;
    background-color: #fff;
    min-width: 40px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

3. 高德地图切换路由后失效

*解决方法:在加载前,将map置空,异步加载绘制方法,离开页面,销毁掉

  async mounted() {
    console.log('加载中')
    this.map = null
    await this.initMap()
      // 初始完地图后,开始绘制
    setTimeout(() => {
      this.setProvinceParcelFn(chinaData.features)
    }, 1000)
  },
  beforeDestroy() { // 离开页面,销毁掉
    this.map && this.map.destroy()
  },
  

4. 市级图层-需要构造二维数组,优化请求

*解决方法:根据数组中相同的provinceCode来实现是否需要重新加载地块图层
在这里插入图片描述

5. 聚合标注图层

*解决方法: 使用高德的覆盖物组 new window.AMap.OverlayGroup() 优化多个marker

       const provinceMarkers = new window.AMap.OverlayGroup(this.provinceMarkers)

6. 重复添加覆盖物组无法有效清除

*解决方法: this.map.clearMap() 只能使用这个进行全部清除

  • 待优化事项
  • 地块图层是否可以设置图层id来实现显示隐藏
  • 是否能实现聚合效果
;