一、开发文档
点聚合-海量点-进阶教程-地图 JS API 2.0 | 高德地图API
二、效果展示
三、实现途径:
使用高德JS API 2.0 点聚合功能的按索引聚合,具体用到地图plugin为IndexCluster。
AMap.plugin("AMap.IndexCluster", function () {
//在回调函数中实例化插件,并使用插件功能
});
四、前置条件:
1、高德JS API 2.0
点聚合有两种方式:“按距离聚合“”与“”按索引聚合“”。
高德地图版本如1.4.15,没有按索引聚合。所以需使用2.0版本,但2.0版本的索引聚合无点击自动散开功能,因此缩进需手写。
2、需要同时使用key与安全秘钥。
五、要点分析
1、聚合的关键
以官网为例,聚合通过点位数据与聚合规则实现。聚合规则自定义。
points中除了所有点位基本坐标外,还需要加上聚合字段,需与clusterIndexSet中定义一致。
clusterIndexSet可理解为,当地图达到缩放范围,就按给定字段进行聚合。例:当地图缩放等级为2到10之间,按"city"这个字段聚合,即所有points 中 city 字段相同的坐标会聚合成一个点。
//点聚合数据
var points = [
{
lnglat: ["116.506621867519", "39.925077049391"],
building: "晨光家园",
district: "朝阳区",
city: "北京",
},
{
lnglat: ["116.464047215754", "39.871715123709"],
building: "松榆西里",
district: "朝阳区",
city: "北京",
},
{
lnglat: ["116.557773237391", "39.903674644798"],
building: "北花园街6号院",
district: "朝阳区",
city: "北京",
},
];
//定义点聚合规则
var clusterIndexSet = {
city: {
minZoom: 2,
maxZoom: 10,
},
district: {
minZoom: 10,
maxZoom: 12,
},
building: {
minZoom: 12,
maxZoom: 22,
},
};
//使用插件
map.plugin(["AMap.IndexCluster"], function () {
indexCluster = new AMap.IndexCluster(map, points, {
renderClusterMarker: _renderClusterMarker, //自定义聚合点样式
clusterIndexSet: clusterIndexSet, //聚合规则
});
});
2、点样式
聚合点样式通常需要自定义,修改地方见于_renderClusterMarker。
map.plugin(["AMap.IndexCluster"], function () {
indexCluster = new AMap.IndexCluster(map, points, {
renderClusterMarker: _renderClusterMarker, //此函数中自定义样式
clusterIndexSet: clusterIndexSet, //聚合规则
});
});
context 是返回的聚合点数据。内容包括当前聚合的数量,聚合的规则字段,以及坐标数据等。
context.marker.setContent传入自定义样式模版。
//聚合点样式
var _renderClusterMarker = function (context) {
//context 为回调参数,
//包含如下属性 marker:当前聚合点,count:当前聚合点内的点数量
var clusterCount = context.count; //聚合点内点数量
context.marker.setContent(
'<div style="background-color:#00ff00">' + clusterCount + "</div>"
);
};
3、手写缩进
思路:mainKey接收聚合规则字段,根据mainKey判断需要缩进的聚合点(最后一层,点位散开时不再缩进)。
给需要缩进的聚合点添加点击事件,事件中按第一条数据的坐标为中心点进行缩进。
var _renderClusterMarker = function (context) {
const mainKey = context.index.mainKey;
const data = context.clusterData[0];
const zoomCenter = [context.clusterData[0].lnglat.lng, context.clusterData[0].lnglat.lat]
if (mainKey == "city" || mainKey == "areaName") {
//缩放
context.marker.on('click', (e) => {
var center =[e.lnglat.lng, e.lnglat.lat];
if(mainKey == "city" ) {
map.setZoomAndCenter(10, zoomCenter);
}
if(mainKey == "areaName" ) {
map.setZoomAndCenter(14, zoomCenter);
}
})
}
};
六、完整的简单代码示例。
<template>
<div id="container"></div>
</template>
<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
import { shallowRef } from '@vue/reactivity';
import { onBeforeMount, ref, watch, onMounted, ***puted } from 'vue';
let map;
let geocoder;
const amap = shallowRef(null);
const geolocation = shallowRef(null);
const clusterIndexSet = {
//定义点聚合规则
city: {
minZoom: 2,
maxZoom: 10,
},
district: {
minZoom: 10,
maxZoom: 12,
},
building: {
minZoom: 12,
maxZoom: 22,
},
};
const points = [
{
lnglat: ["116.506621867519", "39.925077049391"],
building: "晨光家园",
district: "朝阳区",
city: "北京",
houseOriginalMin: 800,
houseCount: 10,
},
{
lnglat: ["116.464047215754", "39.871715123709"],
building: "松榆西里",
district: "朝阳区",
city: "北京",
houseOriginalMin: 800,
houseCount: 10,
},
{
lnglat: ["116.557773237391", "39.903674644798"],
building: "北花园街6号院",
district: "朝阳区",
city: "北京",
houseOriginalMin: 800,
houseCount: 10,
},
{
lnglat: ["116.40499876945", "39.958000356032"],
building: "安定门外大街80号院",
district: "东城区",
city: "北京",
houseOriginalMin: 800,
houseCount: 90,
},
{
lnglat: ["116.412789588355", "39.957363077042"],
building: "地坛北门",
district: "东城区",
city: "北京",
houseOriginalMin: 800,
houseCount: 90,
},
];
onMounted(() => {
initMap();
})
const initMap = () => {
AMapLoader.load({
key: 'd51aa86dd58525a4a0d9368630f78120',
version: '2.0',
AMapUI: { // 是否加载 AMapUI,缺省不加载
version: '1.1', // AMapUI 缺省 1.1
plugins: [], // 需要加载的 AMapUI ui插件
},
plugins: ['AMap.Geolocation', 'AMap.Auto***plete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.IndexCluster']
})
.then(AMap => {
amap.value = AMap;
map = new AMap.Map('container', {
// viewMode: '2D', //是否为3D地图模式
zoom: 11, //初始化地图级别
// zooms: [6, 18],
// dataZooms: [1, 22],
animateEnable: true,
// expandZoomRange: true,
center: [116.405285, 39.904989]//初始化地图中心点位置
});
cluster = new AMap.IndexCluster(map, points, {
renderClusterMarker: _renderClusterMarker,
clusterIndexSet: clusterIndexSet,
});
})
.catch(e => {
console.log(e);
});
};
//聚合点样式
var _renderClusterMarker = function (context) {
const mainKey = context.index.mainKey;
const data = context.clusterData[0];
let text;
const zoomCenter = [context.clusterData[0].lnglat.lng, context.clusterData[0].lnglat.lat]
// 获取点击位置的经纬度
if (mainKey == "building") {
context.marker.setContent(
`<div style="padding: 8px 16px;white-space: nowrap;border-radius: 74px; background: #DA0004; color: #fff">${data.building}¥${data.houseOriginalMin}起(${data.houseCount}套)</div>`
)
} else if (mainKey == "district" || mainKey == "city") {
context.marker.setContent(
`<div style="
display: flex;
align-items: center;
justify-content: center;
background-color:#DA0004;
width: 100px;height: 100px;
color: #fff;
border-radius: 280px;
flex-direction: column;">
<div style="font-size: 16px">${data[mainKey]}</div>
<div style="font-size: 13px">项目: ${context.count}</div>
</div>`
);
//缩放
context.marker.on('click', (e) => {
var center = [e.lnglat.lng, e.lnglat.lat];
if (mainKey == "city") {
map.setZoomAndCenter(10, zoomCenter);
}
if (mainKey == "district") {
map.setZoomAndCenter(12, zoomCenter);
}
})
}
};
</script>
<style scoped>
#container {
padding: 0px;
margin: 0px;
width: 100%;
height: 100%;
}
</style>