使用vue和高德地图,仿58地图找房pc端,且解决marker过多卡顿

1.在index.html引入高德地图链接
https://webapi.amap.com/maps?v=1.4.15&key=你的key&plugin=AMap.Geocoder,AMap.Autocomplete,AMap.PlaceSearch,AMap.InfoWindow

2.https://webapi.amap.com/demos/js/liteToolbar.js 工具栏

3.本来用vue3.0,写的,改成了html,可根据自己需求修改
源码地址 下载

最开始的思路:最开始是想用 高德地图点聚合来写(官网点聚合),但是点聚合聚合区域计算方式不适用省市区,或者是行政区划聚合官网行政区划聚合),奈何小弟能力有限,很多事件都想控制,但是找不到。。。

最后思路:后来想到,可以搞个假的聚合,像聚合就行啊。

  1. 在地图当前zoom层级小于8的时候 ,显示省级的marker标记点。
  2. 地图 8<=zoom<=10 的时候,清空地图上的marker标记,显示市级的标记点
  3. 地图 10<zoom<14 的时候,清空地图上的marker标记,显示区级的标记点
  4. 地图 zoom>=14 的时候,清空地图上的marker标记,显示门店的标记点
  5. 当门店数据过多,一次性加载在地图上,肯定会卡顿很长时间,那我们就利用地区的可视区域AMap.GeometryUtil.isPointInRing()方法,如果门店经纬度在可视区域,才在地图上加载marker.

先上效果图

省级效果图 在这里插入图片描述
市级效果图
在这里插入图片描述
区级效果图
在这里插入图片描述
门店效果图
在这里插入图片描述

好了现在根据思路来一步步实现

  1. 首先先实现清除地图上的所有marker方法和判断经纬度是否在可视区域的方法
    //清除marker标记
    function clearMarker() {
         map.clearMap()
    }
    
    /**规划处地图的可视范围,且判断经纬度是否在当前可视区域
 	* @param {string} center
 	* @returns {Boolean}
 	*/
      function logMapBounds(center) {  center是经纬度字符串,用","拼接
        var point= center.split(',')
        var bounds = map.getBounds();  
        const NorthEast = bounds.getNorthEast();
        const SouthWest = bounds.getSouthWest();
        const SouthEast = [NorthEast.lng, SouthWest.lat];
        const NorthWest = [SouthWest.lng, NorthEast.lat];
        const path = [[NorthEast.lng, NorthEast.lat], SouthEast, [SouthWest.lng, SouthWest.lat], NorthWest]
        return AMap.GeometryUtil.isPointInRing(point,path); 
      }

2.点击省市区marker转到相应层级和显示对应marker

//点击省,到市级,点击市到区级,点击区到门店
      function showInfoM (e){
        let level=map.getZoom()
        let zooms,centers;
          if(level<8){
            zooms=8
          }else if(level>=8&&level<11){
            zooms=11
          }else if(level>=11&&level<15){
            zooms=15
          }
          centers=[e.target.Ce.position.lng,e.target.Ce.position.lat]
          map.setCenter(centers)
          map.setZoom(zooms)
      }

3.由于省市区的marker一样,所以创建省市区的marker
creatMarker(data) 里面的data是请求后台接口返回的数据

数据格式 	 data:[{
					baseAreaCenter: "116.405285,39.904989",
					baseAreaCode: "11",
					baseAreaName: "北京市", //省code
					count: 5
				}]
//添加省级或市级或区级marker
    function creatMarker(data){  //data数据格式见上面代码块
        clearMarker()
        for(let i=0;i<data.length;i++){
            var div=`<div class="circle" center=${data[i].baseAreaCenter}>
                <div>
                    <div>${data[i].baseAreaName} </div><div>${data[i].count}</div>
                </div>
            </div>`
            if(logMapBounds(data[i].baseAreaCenter)){
                markers = new AMap.Marker({
                  content:div,
                  areaCode:data[i].baseAreaCode,
                  position:data[i].baseAreaCenter.split(","),
                  offset: new AMap.Pixel(-24, 5),
                  zIndex: data[i].count,
                  map:map
               });
              markers.on('click', showInfoM);  //省市区marker点击事件  见代码快2的showInfoM方法
            }
        }
    }

4.增加门店的marker

//创建门店marker
    function creatShopMarker(data){
      clearMarker()
      for (var i = 0; i < data.length; i++) {
          if(logMapBounds(data[i].baseAreaCenter)){
              var marker = new AMap.Marker({
                  position: data[i].baseAreaCenter.split(','),
                  icon: require('@/assets/marker.svg'),
                  size:[32,43],
                  imageSize: new AMap.Size(32,43),
                  map: map
              });
              marker.content =`<div><span style="color:#31C0FD">${data[i].brandName}</span> ${data[i].storesAreaName}</div>`;
              marker.on('click', markerClick);
          }
      }
    }
    
	//点击门店marker时触发的事件
    function markerClick(e){
      infoWindow.setContent(e.target.content);
      infoWindow.open(map, e.target.getPosition());
    }

5.当地图缩放和左右平移的时候 都要重新渲染地图上的marker

const init = () => {
      //初始化地图容器
      marker, map = new AMap.Map("container", {
        resizeEnable: true,
        zoom: 5,
        zooms: [5, 18],
        center: [106.49, 34.6],
      });

      AMap.plugin(['AMap.ToolBar','AMap.Scale','AMap.ControlBar'],function(){ 
      //创建放大缩小控件
        map.addControl(new AMap.ToolBar({
          position:'RB', //定位在地图右下角
          locate:false, //不显示定位按钮
          ruler:true,//显示定位按钮标尺
          direction:false, //不显示移动按钮
          offset:new AMap.Pixel(59,24)
        }));

        //比例尺控件
        map.addControl(new AMap.Scale());

        // 添加 3D 罗盘控制
       map.addControl(new AMap.ControlBar({
         showZoomBar:false,//不显示缩放按钮  
         showControlButton:false //不显示显示倾斜、旋转按钮
       }));
      })

      //创建信息窗体
      infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -30)});

      //map绑定滚动结束事件  
      map.on('zoomend', mapZoomend);

      //map拖拽结束事件
      map.on('moveend', mapMoveEnd);

      //首次加载省的marker
      creatMarker(state.provinces)
      
    };

6.地图缩放对应事件和地图平移缩放事件

  //地图层级放大缩小的事件
    function mapZoomend(){
          let level=map.getZoom()
          state.level=level
          if(level<8){
            getCurrentProMap().then(res=>{
              if(res.code==200){
                clearMarker()
                creatMarker(state.provinces)
              }
            })
          }else if(level>=8&&level<=10){
             getCurrentCityMap().then(res=>{
              if(res.code==200){
                clearMarker()
                creatMarker(state.citys)
              }
             })
          }else if(level>10&&level<14){
             getCurrentAreaMap().then(res=>{
               if(res.code==200){
                 clearMarker()
                 creatMarker(state.areas)
               }
             })
          }else if(level>=14){
            getCurrentStoreMap().then(res=>{
              if(res.code==200){
                clearMarker()
                creatShopMarker(state.shop)
              }
            })
          }
      }

		//地图拖动结束时的事件
    function mapMoveEnd(){
      let level=map.getZoom()
        state.level=level
        clearMarker()
        if(level<8){
          creatMarker(state.provinces)
        }else if(level>=8&&level<=10){
          creatMarker(state.citys)
        }else if(level>10&&level<14){
          creatMarker(state.areas)
        }else if(level>=14){
          creatShopMarker(state.shop)
        }
    }

7.接下来是请求省市区门店四个接口,可根据自己的 公司需求修改

//获取省的数据
    const getCurrentProMap=()=>{
      return new Promise((resolve,reject)=>{
        let params={
          enterpriseCode:state.enterpriseCode
        }
        getProvinceMap(params).then(res=>{
          if(res.code==200){
            state.provinces=res.data
          }
          resolve(res)
        }).catch(err=>{
          reject(err)
        })
      })
      
    }

    //获取市的数据
    const getCurrentCityMap=()=>{
      return new Promise((resolve,reject)=>{
        let params={
          enterpriseCode:state.enterpriseCode
        }
        getCityMap(params).then(res=>{
          state.citys=res.data
          resolve(res)
        }).catch(err=>{
          reject(err)
        })
      })
    }

    //获取区的数据
    const getCurrentAreaMap=()=>{
      return new Promise((resolve,reject)=>{
        let params={
          enterpriseCode:state.enterpriseCode
        }
        getAreaMap(params).then(res=>{
          state.areas=res.data
          resolve(res)
        }).catch(err=>{
          reject(err)
        })
      })
    }

    //获取品牌门店数据
    const getCurrentStoreMap=(data)=>{
      return new Promise((resolve,reject)=>{
        let params={
          enterpriseCode:state.enterpriseCode,
        }
        if(data)params.baseAreaCode=data
        else delete params.baseAreaCode
        getStoreMap(params).then(res=>{
          state.shop=res.data
          resolve(res)
        }).catch(err=>{
          reject(err)
        })
      })
    }
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐