<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<title></title>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key={高德key}"></script>
<style type="text/css">
#container {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
<script>
Utils = {
// 计算距离,km
getDistance(lat1, lng1, lat2, lng2) {
var radLat1 = lat1 * Math.PI / 180.0;
var radLat2 = lat2 * Math.PI / 180.0;
var a = radLat1 - radLat2;
var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137; // EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
},
//计算聚集质心坐标
centroid(clusters) {
if (clusters && clusters.length > 0) {
var x = 0;
var y = 0;
var newBoats = clusters.filter(item => parseFloat(item.lat).toString() != "NaN" && parseFloat(item.long).toString() !=
"NaN");
for (var i = 0; i < newBoats.length; i++) {
x += newBoats[i].long;
y += newBoats[i].lat;
}
if (newBoats.length > 0) {
return {
'long': x / newBoats.length,
'lat': y / newBoats.length
};
}
}
},
//缩放比例尺,缩放-距离,圆半径
getEatRadius(scale) {
var number = parseInt(scale);
switch (number) {
case 3:
return 1000;
case 4:
return 500;
case 5:
return 200;
case 6:
return 100;
case 7:
return 50;
case 8:
return 30;
case 9:
return 20;
case 10:
return 10;
case 11:
return 5;
case 12:
return 2;
case 13:
return 1;
case 14:
return 0.5;
case 15:
return 0.2;
case 16:
return 0.1;
case 17:
return 0.05;
case 18:
return 0.025;
default:
return 50;
}
},
//计算聚集
comobine2(clusters,eatRadius,temp){
if(clusters.length<1){
return temp;
}
var cluster=clusters.pop();
var next = [];
for (var i = 0; i < clusters.length; i++) {
if(!cluster.eat2(clusters[i],eatRadius)){
next.push(clusters[i]);
}
}
temp.push(cluster);
Utils.comobine2(next,eatRadius,temp);
},
//测试数据
generatorClusters() {
var latlong = [
[116.455788, 39.920767],
[116.456065, 39.920965],
[116.452312, 39.92304],
[116.421385, 39.989539],
[116.455685, 39.92069],
[116.455876, 39.920845],
[116.455973, 39.920902],
[116.455645, 39.920657],
[116.456022, 39.920934],
[116.455685, 39.920691],
[116.456023, 39.920671],
[116.45596, 39.920864],
[116.455522, 39.920856],
[116.455276, 39.920407],
[116.455799, 39.920867],
[116.455349, 39.920425],
[116.45511, 39.920377],
[116.455318, 39.920442],
[116.455298, 39.920474],
[116.455839, 39.920636],
[116.455979, 39.921168],
[116.454281, 39.920006],
[116.45598, 39.920612],
[116.45388, 39.919584],
[116.455474, 39.920737],
[116.456009, 39.920641],
[116.455439, 39.920574],
[116.455759, 39.920841],
[116.455838, 39.920644],
[116.455983, 39.920847],
[116.459803, 39.922041],
[116.456029, 39.92088],
[116.455539, 39.920603],
[116.455989, 39.920851],
[116.455719, 39.920789],
[116.45601, 39.92082],
[116.456229, 39.920564],
[116.455906, 39.920771],
[116.456248, 39.920868],
[116.455805, 39.920544],
[116.455896, 39.920758],
[116.43692, 39.926767],
[116.454672, 39.92024],
[116.454813, 39.917848],
[116.381415, 40.00875],
[116.422925, 39.980757],
[116.422849, 39.9808],
[116.38107, 40.009217],
[116.456078, 39.920747],
[116.455242, 39.919515],
[116.455615, 39.920533],
[116.422092, 39.991104],
[116.454847, 39.917724],
[116.456686, 39.924316],
[116.45575, 39.920642],
[116.456713, 39.924413],
[116.455846, 39.920828],
[116.422108, 39.991098],
[116.422075, 39.991139],
[118.775572, 31.97337],
[118.776968, 31.97392],
[118.778187, 31.973121],
[118.775695, 31.973254],
[118.775302, 31.973807],
[118.776303, 31.973692],
[118.777541, 31.973439],
[118.776196, 31.973489],
[116.448944, 39.926799],
[116.45487, 39.917804],
[116.455762, 39.920645],
[116.456146, 39.920441],
[116.455857, 39.920043],
[116.455458, 39.920826],
[116.455533, 39.920791],
[116.455426, 39.920896],
[116.45566, 39.920811],
[116.455696, 39.920621],
[116.453667, 39.9259],
[116.466606, 39.886322],
[116.455917, 39.92062]
];
var boats = [];
var clusters = [];
for (var i = 0; i < latlong.length; i++) {
clusters.push(new Cluster(new Boat({
'boatLongitude': latlong[i][0],
'boatLatitude': latlong[i][1],
'boatName': '第' + (i + 1) + '船'
})))
}
return clusters;
}
}
//船
class Boat {
constructor(orign) {
this.lat = orign.boatLatitude;
this.long = orign.boatLongitude;
this.name = orign.boatName;
}
//计算两搜船的距离
distance(boat) {
return Utils.getDistance(this.lat, this.long, boat.lat, boat.long)
}
getSize() {
return 1;
}
}
//一个聚集
class Cluster {
constructor(boat) {
this.boats = [];
this.boats.push(boat);
this.size = this.boats.length;
this.lat = boat.lat;
this.long = boat.long;
}
addBoat(boat) {
this.boats.push(boat);
this.centroid();
}
getBoat(){
return this.boats[0];
}
getSize() {
return this.boats.length;
}
//计算两个聚集的距离
distance(cluster) {
return Utils.getDistance(this.lat, this.long, cluster.lat, cluster.long)
}
//吞食2
eat2(cluster, radius) {
//吞噬
this.addBoat(cluster.getBoat());
this.centroid();
//计算是否吞噬溢出
for (var i = 0; i < this.boats.length; i++) {
if (this.distance(this.boats[i]) > radius) {
this.boats.pop();
this.centroid();
// console.log(this.boats[0].name+" 吞噬----失败 "+cluster.boats[0].name);
return false;
}
}
// console.log(this.boats[0].name+" 吞噬成功 "+cluster.boats[0].name);
return true;
}
//计算质心坐标
centroid() {
if (this.boats && this.boats.length > 0) {
var x = 0;
var y = 0;
var newBoats = this.boats.filter(item => parseFloat(item.lat).toString() != "NaN" && parseFloat(item.long).toString() !="NaN");
for (var i = 0; i < newBoats.length; i++) {
x += newBoats[i].long;
y += newBoats[i].lat;
}
if (newBoats.length > 0) {
this.long = x / newBoats.length;
this.lat = y / newBoats.length;
this.size = newBoats.length;
}
}
}
}
//高德地图的封装,作为是数据的测试使用
class GMap {
constructor(long, lat, id, zoo,data) {
this.zlat = lat;
this.zlong = long;
this.map = new AMap.Map(id, {
zoom: zoo, //级别
center: [long, lat], //中心点坐标
viewMode: '3D' //使用3D视图
});
this.map.preScale=-1;
this.map.clusterData=data;
this.map.createContent=this.createContent;
this.map.marks=[];
//设置监听
this.map.on("zoomchange", this.listen);
this.listen({'target':this.map})
}
addMark(cluster, color) {
var marker = new AMap.Marker({
position: [cluster.long, cluster.lat],
content: this.createContent(cluster, color),
})
this.map.add(marker);
}
createContent(cluster, color) {
color = color ? color : "black";
var content = '<div class="custom-content-marker">' +
'<img src="//a.amap.com/jsapi_demos/static/demo-center/icons/dir-via-marker.png">' +
'<div class="close-btn" style="position:relative;top:-90px;left:20px;color:' + color + '">' + cluster.getSize() +
'</div>' +
'</div>';
return content;
}
//渲染
drawing(clusters){
for (var i = 0; i < clusters.length; i++) {
this.map.addMark(clusters[i])
}
}
//缩放监听
listen(self) {
var map =self.target;
console.log(map.getZoom()+";"+parseInt(map.getZoom())+";"+Utils.getEatRadius(map.getZoom()))
if(parseInt(map.preScale)!=parseInt(map.getZoom())){
console.log('change')
var newClusters =[];
Utils.comobine2(Utils.generatorClusters(),Utils.getEatRadius(map.getZoom()),newClusters)
console.log(newClusters)
for (var i = 0; i < map.marks.length; i++) {
map.remove(map.marks[i]);
}
var marks=[];
for (var i = 0; i < newClusters.length; i++) {
var marker = new AMap.Marker({
position: [newClusters[i].long, newClusters[i].lat],
content: map.createContent(newClusters[i], 'black'),
})
map.add(marker);
marks.push(marker);
}
map.marks=marks
}
map.preScale=map.getZoom();
}
}
//初始聚合半径
var eatRadius = 5;
var clusters = Utils.generatorClusters();
var clustersNoDispear=[]
Utils.comobine2(clusters,eatRadius,clustersNoDispear)
console.log("获取没有消失的集群")
console.log(clustersNoDispear)
//获取最大集群的经纬度
var dsize = 0;
var dlatlong = {};
for (var i = 0; i < clustersNoDispear.length; i++) {
if (clustersNoDispear[i].getSize() > dsize) {
dsize = clustersNoDispear[i].getSize();
dlatlong = clustersNoDispear[i];
}
}
var gmap = new GMap(dlatlong.long, dlatlong.lat, "container", 10,Utils.generatorClusters());
</script>
</html>
地图聚合简单实现,基于实际范围,测试需要填写高德key
猜你喜欢
转载自blog.csdn.net/INK_FUNC/article/details/103929251
今日推荐
周排行