高德地圖js2.0使用MarkerCluster聚合點(diǎn)及添加點(diǎn)擊事件

高德地圖也在不斷迭代,目前2.0以下版本已經(jīng)在iOS15 beta版本不適用了,而且2.0以下版本由于卡頓等問(wèn)題也不在符合用戶的使用需要,升級(jí)迫在眉睫,但2.0對(duì)于標(biāo)記的聚和與之前版本有較大區(qū)別,在此將寫法記錄一下,也希望能幫到大家。

2.0以前對(duì)于標(biāo)記的處理是將標(biāo)記全部在地圖上畫出來(lái)之后通過(guò)MarkerClusterer聚合,不僅對(duì)標(biāo)記的修改較為復(fù)雜,還會(huì)導(dǎo)致嚴(yán)重的卡頓問(wèn)題。而在升級(jí)到2.0后,標(biāo)記的聚合便是通過(guò)MarkerCluster將標(biāo)記的坐標(biāo)打在地圖上,然后直接渲染的方式了,如下所示:

方式一:
      this.cluster = new AMap.MarkerCluster(this.map, this.allLnglat, {
            styles: styles,
            renderMarker: this.renderMarker
      });

其中只列舉出了最重要的幾個(gè)參數(shù):

  • this.map:當(dāng)前渲染的地圖

  • this.allLnglat:所有的標(biāo)記坐標(biāo),例如:[{ lnglat: [117.366,36.577] }]

  • styles: 聚合點(diǎn)上顯示的圖標(biāo),例如:

    [{
     url: 'https://a.amap.com/jsapi_demos/static/images/blue.png',
     size: new AMap.Size(32, 32),
     offset: new AMap.Pixel(-16, -16)
    },{
     url: 'https://a.amap.com/jsapi_demos/static/images/green.png',
     size: new AMap.Size(32, 32),
     offset: new AMap.Pixel(-16, -16)
    }]
    
    • renderMarker:非聚合點(diǎn)上顯示的標(biāo)記,也就是單個(gè)點(diǎn)顯示的標(biāo)記,和2.0版本前我們定義的marker是一個(gè)東西,可以自定義樣式添加點(diǎn)擊事件等,例如:

      renderMarker(context) {
      //顯示點(diǎn)的經(jīng)緯度context.data[0].lnglat
      //此處應(yīng)有邏輯,通過(guò)遍歷所有點(diǎn)的經(jīng)緯度來(lái)識(shí)別當(dāng)前標(biāo)記對(duì)應(yīng)的數(shù)據(jù)
      //此處content為設(shè)置當(dāng)個(gè)標(biāo)記的樣式
      context.marker.setContent(content);
      //此處為設(shè)置標(biāo)記在地圖上的偏移,根據(jù)標(biāo)記物大小處理
      context.marker.setOffset(new AMap.Pixel(-20, -20));
      //此處為設(shè)置標(biāo)記是否顯示在最上方,一般只有選中的標(biāo)記在最上方
      context.marker.setTop(top);
      //此處為設(shè)置標(biāo)記攜帶的數(shù)據(jù),點(diǎn)擊事件會(huì)使用
      context.marker.setExtData({
         id: id
       });
      //此處為添加單個(gè)標(biāo)記點(diǎn)擊事件
        context.marker.on('click', ev => {
            //當(dāng)前標(biāo)記居中
           this.map.setZoomAndCenter(16, ev.target.getPosition());
           //獲取標(biāo)記攜帶的數(shù)據(jù)
           const extData = ev.target.getExtData();
           const id = extData.id;
         });
        },
      

由于現(xiàn)在聚合點(diǎn)和標(biāo)記點(diǎn)都是使用的標(biāo)記,因此聚合點(diǎn)沒(méi)有提供點(diǎn)擊散開的功能,我們可以通過(guò)一下方式實(shí)現(xiàn):

 this.cluster.on('click', (item) => {
    //此處是通過(guò)包含點(diǎn)的數(shù)量判斷是否是聚合點(diǎn),不是聚合點(diǎn)就執(zhí)行上方單個(gè)點(diǎn)的點(diǎn)擊方式
   if(item.clusterData.length <= 1) {
     return;
   }
   //這里是計(jì)算所有聚合點(diǎn)的中心點(diǎn)
   let alllng = 0, alllat = 0;
  for(const mo of item.clusterData) {
    alllng += mo.lnglat.lng;
    alllat += mo.lnglat.lat;
   }
   const lat = alllat / item.clusterData.length;
   const lng = alllng / item.clusterData.length;
     //這里是放大地圖,此處寫死了每次點(diǎn)擊放大的級(jí)別,可以根據(jù)點(diǎn)的數(shù)量和當(dāng)前大小適應(yīng)放大,體驗(yàn)更佳
    this.map.setZoomAndCenter(this.map.getZoom() + 2, [lng, lat]);
 });
方式二:
    new AMap.MarkerClusterer(
     //地圖實(shí)例對(duì)象
      map:Map,  
     //經(jīng)緯度數(shù)組對(duì)象
     dataOptions:Array   
     //點(diǎn)聚合屬性
     markerClusterOptions:Object 
 )

  dataOptions:[
      {
       weight: Number, //權(quán)重(可選)以權(quán)重高的點(diǎn)為中心進(jìn)行聚合
       lnglat: Array //經(jīng)緯度數(shù)組 string[] | number[]
      }
    ]

在2.0版本中,markerClusterOptions去掉了minClusterSize 集合的最小數(shù)量,zoomOnclick 點(diǎn)擊聚合點(diǎn)時(shí)是否散開;對(duì)renderClusterMarker屬性進(jìn)行了修改,去掉了renderClusterMarker:function的markers屬性;新增了renderMarker: function 用于實(shí)現(xiàn)非聚合點(diǎn)的自定義設(shè)置

  new AMap.MarkerClusterer(map, marker, { 

   gridSize: number, //聚合計(jì)算時(shí)網(wǎng)格的像素大小,默認(rèn)60
   //minClusterSize 聚合的最小數(shù)量(已棄用)
   maxZoom: number, //最大聚合級(jí)別,超出級(jí)別不進(jìn)行聚合,默認(rèn)18
   averageCenter: boolean, //聚合點(diǎn)的圖標(biāo)位置是否是所有聚合內(nèi)點(diǎn)的中心點(diǎn),默認(rèn)true,如果有權(quán)重則以權(quán)重高的為中心進(jìn)行聚合
   clusterByZoomChange: boolean, //地圖縮放過(guò)程中是否聚合,默認(rèn)false
   styles: Array<Object>, //聚合后點(diǎn)標(biāo)記樣式
   // styles包含以下屬性
   // url{string} (必選)圖標(biāo)的url地址
   // size{AMap.Size} (必選)圖標(biāo)的圖片大小
   // offset{AMap.Pixel} (可選)圖標(biāo)相對(duì)于左上角的偏移量
   // imageOffset{AMap.Pixel} (可選)圖片在可視區(qū)域的偏移量
   // textColor{String} (可選)文字顏色,默認(rèn)#000000
   // textSize{Number} (可選)文字大小,默認(rèn)10
    renderClusterMarker: (cluster: any) => {
       cluster.count //當(dāng)前聚合點(diǎn)下marker的數(shù)量
       cluster.marker //當(dāng)前聚合點(diǎn)的marker對(duì)象
    },
    renderMarker: (context: any) => {
        context.marker //非聚合點(diǎn)的marker對(duì)象
    }
   // zoomOnClick 點(diǎn)擊聚合點(diǎn)時(shí)是否散開(已棄用)

點(diǎn)聚合及點(diǎn)標(biāo)記的鼠標(biāo)移入、移出、點(diǎn)擊效果的實(shí)現(xiàn)(只提供思路,不進(jìn)行數(shù)據(jù)效果實(shí)現(xiàn))

const markerData: any[] //獲取的標(biāo)記坐標(biāo)等信息
const markers: [{
   weight: number, //權(quán)重
   lnglat: number[] | string [], //經(jīng)緯度
   extData:object //其他需要傳遞的信息,如id、name等
}] = [] 


markerData.map((item: any) => {
markers.push({
    weight: item.weight,
    lnglat: [item.lon, item.lat],
    extData: {
        id: item.id,
        icon: url,
        markerIcon: url
       }
     })
  })


  const clu = new AMap.MarkerClusterer(map, markers, {
    //聚合點(diǎn)自定義樣式交互
    renderClusterMarker: (cluster: any) = {
     //marker點(diǎn)標(biāo)記API
     //自定義聚合樣式
    //cluster.data[0].extData可獲取到傳入的其他數(shù)據(jù)
    cluster.marker.setAnchor('bottom-center');
    cluster.marker.setIcon(new AMap.Icon({ image: cluster.data[0].extData.markerIcon }));
    cluster.marker.setLabel({
        content: `<span style="cursor: pointer;">${cluster.count}</span>`,
        direction: 'center',
        offset: new AMap.Pixel(0, -5),
    })
    //添加鼠標(biāo)移入放大效果
    cluster.marker.on('mouseover', () => {
        cluster.marker.setIcon(
            new AMap.Icon({
                image: cluster.marker.getIcon()._opts.image,
                size: new AMap.Size(40, 50), //根據(jù)image分辨率計(jì)算放大后尺寸
                imageSize: new AMap.Size(40, 50),
            }),
        );
        cluster.marker.setLabel({
            content: `<span style="cursor: pointer;font-size: 20px;">${cluster.count}</span>`,
            direction: 'center',
            offset: new AMap.Pixel(0, -5),
        });
    });
    //鼠標(biāo)移出還原
    cluster.marker.on('mouseout', () => {
        cluster.marker.setIcon(
            new AMap.Icon({
                image: cluster.marker.getIcon()._opts.image,
                size: new AMap.Size(32, 40),
                imageSize: new AMap.Size(32, 40),
            }),
        );
        cluster.marker.setLabel({
             content: `<span style="cursor: pointer;">${cluster.count}</span>`,
             direction: 'center',
             offset: new AMap.Pixel(0, -5),
        });
    });
},
//非聚合點(diǎn)自定義樣式交互
renderMarker: (context: any) => {
    context.marker.setAnchor('bottom-center');
    context.marker.setOffset(new AMap.Pixel(0, 0));
    context.marker.setIcon(new AMap.Icon({ image: context.data[0].extData.markerIcon }));
    context.marker.setLabel({
        content: `<img src=${context.data[0].extData.icon} style="cursor: pointer;" />`,
        direction: 'center',
        offset: new AMap.Pixel(0, -5),
    });
    //鼠標(biāo)移入移出同上,不再重復(fù)
    //marker鼠標(biāo)點(diǎn)擊事件
    context.marker.on('click', () => {
        const params = context.data[0].extData;
        console.log(params.id) //id
        });
     }
 })


  //添加聚合點(diǎn)點(diǎn)擊事件
 clu.on('click', (data: any) => {
//判斷是否是聚合點(diǎn),不是聚合點(diǎn)就執(zhí)行單個(gè)點(diǎn)擊方式
 if (data.clusterData.length <= 1) return;
//計(jì)算所有聚合點(diǎn)的中心點(diǎn)
    let alng = 0,
    alat = 0;
     for (const m of data.clusterData) {
        alng += m.lnglat.lng;
        alat += m.lnglat.lat;
     }
     const lat = alat / data.clusterData.length;
     const lng = alng / data.clusterData.length;
   //以中心點(diǎn)固定倍數(shù)放大地圖,達(dá)到展開聚合點(diǎn)的效果
   map.setZoom(10);
   map.setCenter([lng, lat]);
 });
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容