1. 程式人生 > >基於高德地圖為底圖實現全國、省、地級市下鑽

基於高德地圖為底圖實現全國、省、地級市下鑽

目錄

簡介

效果圖

具體實現

注意點

不足點

簡介

由於前面通過echarts和百度地圖都沒能實現理想效果從而只能另尋方案,最終實現方案:全國省採用echarts渲染,單個省、地級市採用高德地圖為地圖渲染(有人可能會疑問為什麼不全部採用高德地圖渲染,在上一篇中我有解釋到用高德地圖渲染全國省時,由於資料量過於太大會導致卡頓)

效果圖

全國

單個省

可通過放大地圖,展示 行政區詳情

地級市

具體實現

該專案基於vue開發(原生js原理一樣)

1、全國省

參考echarts4.0渲染全國省,這個相當比較簡單,下面提供部分核心程式碼

<EChart :auto-resize="true" :options="options"  v-show="!isShowAMap" @click="getSubMap" ref="theEchart"></EChart>

options:和echarts官網一樣配置相應的引數即可

isShowAMap:是否展示echarts,用於和高德地圖的動態切換

getSubMap: 獲取子地圖(即:高德地圖渲染單個省、地級市)

2、單個省、地級市

<div id="theMap" class="b-map" :style="{display:isShowAMap ? 'block':'none'}"></div>
     /**
       * 初始化 高德地圖
       * */
      initMap(){
        this.theMap = new AMap.Map('theMap',{
          resizeEnable: true,   // 是否監控地圖容器尺寸變化
          mapStyle:'amap://styles/0f97185f111252fe66c244d53f2d0cdd', //自定義底圖
          zoom:6,//縮放級別
        })
        // 關閉 mapTip 區域詳情提示
        this.theMap.on('mouseout',()=>{
          this.mapTip.isShowMapTip = false
        })
        // 監控地圖放大級別,從而控制覆蓋層Text 顯隱
        this.theMap.on('zoomchange',()=>{
          let ele = document.getElementsByClassName('amap-markers')[0]
          if(ele){
            let status = window.getComputedStyle(ele).display
            if(this.theMap.getZoom() > 8 && status === 'none'){
              document.getElementsByClassName('amap-markers')[0].className =  'amap-markers'
            }
            if(this.theMap.getZoom() < 8 && status === 'block'){
              document.getElementsByClassName('amap-markers')[0].className =  'amap-markers amap-markers-none'
            }
          }
        })
      },
      /**
       * 渲染 每個區域塊 地圖資料
       * */
      renderEveryAreaData(){
        if(this.areaInfo.curLevel == 'china'){
          // 渲染全國地圖  echarts
          this.renderChinaMap()
        }else{
          // 渲染省、市地圖  AMap
          this.renderSubMap()
        }
      },
   
      /**
       * 渲染 子地圖(省、市) 高德
       * */
      renderSubMap(){
        const loading = this.$loading(this.zParam.pageLoading);
        try{
          this.isShowAMap = true
          this.isChinaMap = false
          this.theMap.clearMap();        //清除地圖覆蓋物
          AMap.service(['AMap.DistrictSearch','AMap.Geocoder'],()=> {
            let district = new AMap.DistrictSearch({
              subdistrict: 1,   //返回下一級行政區
              extensions: 'all',  //返回行政區邊界座標組等具體資訊 level: 'district'  //查詢行政級別為 區(無效)
            })
            let geocoder = new AMap.Geocoder({
              city: '全國'// city 指定進行編碼查詢的城市,支援傳入城市名、adcode 和 citycode
            })
            this.curMapData.forEach(item => {
              this.renderAMap(item ,district,geocoder)
            })
          })
          loading.close()
        }catch (err){
          console.log(err)
          loading.close()
        }
      },
      /**
       * 根據 data  渲染高德 地圖省市
       * */
      renderAMap(item,district,geocoder){
        // 特別行政區、臺灣 由於無法獲取市級區域 不下鑽
        if(this.areaInfo.province == '香港特別行政區' || this.areaInfo.province == '澳門特別行政區' || this.areaInfo.province == '臺灣'){
           color = '#f1f2f3'
           item = {name:this.areaInfo.province,value:1,noText:true}
        }
        //獲取行政區域,
        //注意:存在相同 行政區(重慶江北、杭州寧波江北),地級市與縣級市同名(峨眉山市、眉山市),高德地圖是模糊匹配的(即:搜尋眉山市 會匹配到 眉山市、峨眉山市)
        district.search(item.name, (status, result) => {
          if(status != 'complete'){return}
          let bounds = []
          // 常規  獲取單個省、市、區(不存在重名情況)
          if(result.districtList.length === 1){
            bounds = result.districtList[0].boundaries
            this.renderAMapByPolygon(item ,bounds ,result.districtList[0].center)
            return
          }
          // 地級市與縣級市模糊匹配(峨眉山市、眉山市),且都不屬於同一層級
          if(this.areaInfo.curLevel === 'province' && result.districtList.length > 1){
            for(let i=0;i<result.districtList.length;i++){
              if(result.districtList[i].level === 'city'){
                bounds = result.districtList[i].boundaries
                this.renderAMapByPolygon(item ,bounds ,result.districtList[0].center)
                return
              }
            }
          }
          // 相同行政區(重慶江北、杭州寧波江北),且都屬於同一層級
          if(this.areaInfo.curLevel === 'city' && result.districtList.length>1){
            for(let i=0;i<result.districtList.length;i++){
              geocoder.getAddress([result.districtList[i].center.lng,result.districtList[i].center.lat], (status, addrResult)=> {
                if(status === 'complete'){
                  let addr = addrResult.regeocode.addressComponent
                  if(addr.city === this.areaInfo.city || addr.province.slice(0,addr.province.length-1) === this.areaInfo.province ){
                    bounds = result.districtList[i].boundaries
                    this.renderAMapByPolygon(item ,bounds ,result.districtList[0].center)
                    return
                  }
                }
              })
            }
          }
        })
      },
      /**
       * 渲染 覆蓋層Polygon、Text
       * */
      renderAMapByPolygon(item ,bounds ,center){
        let color = ''
        // 獲取 區域填充色
        for(let key in this.colors){
          if(item.value >= parseFloat(key)){
            color = this.colors[key]
            break
          }
        }
        if (bounds) {
          for (let i = 0;i < bounds.length; i++) {
            let polygon = new AMap.Polygon({
              map: this.theMap,
              strokeWeight: 1,
              path: bounds[i],
              strokeColor: '#666666',
              fillColor: color,
              cursor:'pointer'
            });
            // 香港、澳門、臺灣暫不支援下鑽地圖
            if(this.areaInfo.province != '香港特別行政區' && this.areaInfo.province != '澳門特別行政區' && this.areaInfo.province != '臺灣'){
              polygon.on('click', () => {
                this.getAMapSubArea(item.name)
              })
              polygon.on('mouseover', (e) => {
                this.mapTip.isShowMapTip = true
                this.mapTip.info = item.name + ':'+ this.zMethod.formatPercent(item.value)
              })
              polygon.on('mouseout', (e) => {
                this.mapTip.isShowMapTip = false
                this.mapTip.info = item.name + ':'+ this.zMethod.formatPercent(item.value)
              })
            }
          }
          // 覆蓋層Text,展示區域資訊詳情
          new AMap.Text({
            text: item.name + (item.noText===true ? '': '(' + this.zMethod.formatPercent(item.value)+')')  ,
            map: this.theMap,
            position:[center.lng,center.lat],
            style:{
              color : "#000",
              fontSize : "12px",
              backgroundColor:'transparent',
              border:'none',
            },
          })
        }
        this.theMap.setFitView();//地圖自適應
      },

說明:為提高使用者體驗,初始時不展示行政區詳細資訊,通過放大地圖或滑鼠hover再展示詳細,且滑鼠移動到具體行政區時高亮。echarts 與AMap切換通過動態控制顯隱,返回上一層原理也一樣,高德地圖單個省下鑽地級市通過對行政區的點選動態獲取行政區與資料來實現,參考renderSubMap、renderAMap這兩個核心方法,高德地圖的具體配置使用可參考官網,本文主要提供思路與方案。

注意點

1、存在相同行政區(重慶江北區、杭州寧波江北區)

2、高德地圖是模糊匹配的(即:搜尋眉山市 會匹配到 眉山市、峨眉山市),不支援級聯方式匹配,如寧波市不能寫成浙江省寧波市

不足點

1、暫時無法獲取香港、澳門、臺灣下級的行政區

2、渲染有部分延遲

3、由於高德地圖行政區獲取是單表模糊匹配不支援級聯查詢,就導致無法獲取街道詳情(全國存在大量的同名街道、鄉鎮),也就無法支援下鑽鄉鎮詳情