高德地圖也在不斷迭代,目前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]);
});