地图聚合简单实现,基于实际范围,测试需要填写高德key

<!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>


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值