关于arcgis api for js 实现点聚合官方ClusterLayer.js的解释

直接看js代码

参考https://blog.csdn.net/wpz0713/article/details/79298312

define([
    "dojo/_base/declare",
    "dojo/_base/array",
    "esri/Color",
  	"dojo/_base/connect",
  	"esri/geometry/SpatialReference",
  	"esri/geometry/Point",
  	"esri/Graphic",
  	"esri/symbols/SimpleMarkerSymbol",
  	"esri/symbols/TextSymbol",
  	"esri/geometry/support/webMercatorUtils",
  	"esri/PopupTemplate",
  	"esri/layers/GraphicsLayer", "esri/layers/mixins/ScaleRangeLayer"
], function (
  declare, arrayUtils, Color, connect,
  SpatialReference, Point, Graphic, SimpleMarkerSymbol, TextSymbol,webMercatorUtils, 
  PopupTemplate, GraphicsLayer,ScaleRangeLayer
) {
	return GraphicsLayer.createSubclass([ScaleRangeLayer],{
		declaredClass : "ClusterLayer",
		properties : {
			view:null,//当前视图,必须
			map:null,//当前地图,必须
			id:"clusters",//图层id,必须
			data:[],//聚类数据,必须
			field : "clusterCount",//聚类的字段
			distance:100,//距离
			labelColor:"#FFF",//标注颜色,默认为白色
			labelOffset : -4,//标注偏移,默认为-4
			resolution:null,
			clusters : null,
	        singles : null, //单个对象,点击时出现
	        showSingles : true,
	        symbolArray : null,//graphic样式数组
	        singleSym:null,//单个graphic样式
	        graphicSym:null,//要素高亮样式
	        singleTemplate : new PopupTemplate({ "title": "{type}", "description": "{material}" }),
	        spatialReference : null,//空间参考
	        maxSingles : 1000//单个集群最大数
		},
		/**
		 * @description 初始化
		 * @creator 王培珍
		 * @createtime 2018-02-06
		 */
		init:function(){
			this.clusters = [];
			this.singles = [];
			this.spatialReference = this.view.spatialReference;
			if(this.symbolArray == null){
				var red = new SimpleMarkerSymbol("circle", 20, null, new Color("green"));
				var blue = new SimpleMarkerSymbol("circle", 20, null, new Color("blue"));
				var green = new SimpleMarkerSymbol("circle", 20, null, new Color("red"));
				this.symbolArray = [red, blue,green];
			}
		},
		/**
		 * @description 执行点聚合事件
		 * @creator 王培珍
		 * @createtime 2018-02-06
		 */
		excuseClusterEvent: function() {
			//判断当前是否存在该id的图层,若有,删除
			var layer = this.map.findLayerById(this.id);
			if(layer != undefined || layer != null)
				this.map.remove(layer);
			//初始化
			this.init();
			//清除当前图层上的图形
			this.clear();
			//设置Resolution
			this.setResolution(); 
			//创建聚合图形
		    this.clusterGraphics();
		    var div = this.inherited(arguments);
		    return div;
		},

		/**
		 * @description 设置Resolution
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		setResolution: function() {
			var e = this.view.extent;
			var rightTop =  new Point(e.xmax, e.ymax, this.spatialReference); //右上角  
			var leftBottom =  new Point(e.xmin, e.ymin, this.spatialReference); //左下角
			var rightTopPoint = webMercatorUtils.geographicToWebMercator(rightTop);  
			var leftBottomPoint = webMercatorUtils.geographicToWebMercator(leftBottom); 
			this.resolution = (rightTopPoint.x - leftBottomPoint.x) / this.view.width;
		},
		/**
		 * @description 地图缩放处理事件
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		changeExtentEvent:function(){
			//清除当前图层上的图形
			this.clear();
			//设置Resolution
			this.setResolution(); 
			//创建聚合图形
		    this.clusterGraphics();
		},
		/**
		 * @description 移除缩放事件
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
	    removeZoomEnd: function() {
	    	this.inherited(arguments);
	    },

	    /**
		 * @description 添加聚合集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		add : function(p) {
			//判断点是否落在现有集群中,若没有,则新建一个新集群
			if (p.declaredClass) {
				this.inherited(arguments);
				return;
			}

			//把新数据添加到data中
			this.data.push(p);
			//是否添加到集群中
			var clustered = false;
			for (var i = 0; i < this.clusters.length; i++) {
				var c = this.clusters[i];
				//判断两点之间是否属于同一集群
				if (this.clusterTest(p, c)) {
					//添加新点到现有集群
					this.clusterAddPoint(p, c);
					//更新集群图形信息
					this.updateClusterGeometry(c);
					//更新集群label信息
					this.updateLabel(c);
					clustered = true;
					break;
				}
			}

			//如果没有添加到集群中,则创建新集群
			if (!clustered) {
				this.clusterCreate(p);
				p.attributes.clusterCount = 1;
				this.showCluster(p);
			}
		},
		/**
		 * @description 清楚当前所有集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clear : function() {
			var layer = this.map.findLayerById(this.id);
			if (layer != undefined || layer != null)
				layer.removeAll();
			// Summary: Remove all clusters and data
			// points.
			this.inherited(arguments);
			this.clusters.length = 0;
		},

		/**
		 * @description 清除单个集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clearSingles : function(singles) {
			var s = singles || this.singles;
			arrayUtils.forEach(s, function(g) {
				this.remove(g);
			}, this);
			this.singles.length = 0;
		},
		/**
		 * @description 点击集群事件
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		onClick : function(e) {
			this.clear();
			//清除单个要素
			this.clearSingles(this.singles);

			//获取当前集群的数据
			var singles = [];
			for (var i = 0, il = this.data.length; i < il; i++) {
				if (e.attributes.clusterId == this.data[i].attributes.clusterId) {
					singles.push(this.data[i]);
				}
			}
			//判断单个集群长度是否有大于单个集群最大长度
			if (singles.length > this.maxSingles) {
				alert("对不起,当前集群长度大于" + this.maxSingles + "个,请放大到更大级别再进行查询当个集群!");
				return null;
			} else {
				//停止地图点击
				//e.stopPropagation();
				//this.view.popup.content = "<div style='background-color:DarkGray;color:white'> miles.</div>";
				//this.map.infoWindow.show(e.graphic.geometry);
				this.addSingles(singles);
				return singles;
			}
		},

		/**
		 * @description 创建聚合图形
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clusterGraphics : function() {
			for (var j = 0, jl = this.data.length; j < jl; j++) {
				var point = this.data[j];
				var clustered = false;
				var numClusters = this.clusters.length;
				for (var i = 0; i < this.clusters.length; i++) {
					var c = this.clusters[i];
					//判断两点之间是否属于同一集群
					if (this.clusterTest(point, c)) {
						//添加新点到现有集群
						this.clusterAddPoint(point, c);
						clustered = true;
						break;
					}
				}
				//如果没有添加到集群中,则创建新集群
				if (!clustered) {
					this.clusterCreate(point);
				}
			}
			//显示所有集群
			this.showAllClusters();
		},

		/**
		 * @description 判断两点之间是否属于同一个集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clusterTest : function(p, cluster) {
			var c_latlng;
			var p_latlng;
			if (this.spatialReference.isWebMercator) {
				//地图 为WebMercator坐标系
				c_point = new Point(cluster.x,
						cluster.y,
						this.spatialReference);
				p_point = new Point(p.x, p.y,
						this.spatialReference);
			} else {
				//地图为非WebMercator坐标系,则需转换为墨卡托坐标系
				c_latlng = new Point(
						parseFloat(cluster.x),
						parseFloat(cluster.y),
						this.spatialReference);
				p_latlng = new Point(parseFloat(p.x),
						parseFloat(p.y),
						this.spatialReference);
				c_point = webMercatorUtils
						.geographicToWebMercator(c_latlng);
				p_point = webMercatorUtils
						.geographicToWebMercator(p_latlng);
			}
			var distance = (Math.sqrt(Math.pow(
					(c_point.x - p_point.x), 2)
					+ Math.pow((c_point.y - p_point.y),
							2)) / this.resolution);
			return (distance <= this.distance);
		},

		/**
		 * @description 添加新点到现有集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clusterAddPoint : function(p, cluster) {
			//添加新点到现有集群
			var count, x, y;
			count = cluster.attributes.clusterCount;
			x = (p.x + (cluster.x * count))
					/ (count + 1);
			y = (p.y + (cluster.y * count))
					/ (count + 1);
			cluster.x = x;
			cluster.y = y;

			//创建这个集群的新范围
			if (p.x < cluster.attributes.extent[0]) {
				cluster.attributes.extent[0] = p.x;
			} else if (p.x > cluster.attributes.extent[2]) {
				cluster.attributes.extent[2] = p.x;
			}
			if (p.y < cluster.attributes.extent[1]) {
				cluster.attributes.extent[1] = p.y;
			} else if (p.y > cluster.attributes.extent[3]) {
				cluster.attributes.extent[3] = p.y;
			}

			//统计这个集群有多少个点
			cluster.attributes.clusterCount++;
			//判断是否包含attributes字段,若无,赋值
			if (!p.hasOwnProperty("attributes")) {
				p.attributes = {};
			}
			//给这个属性一个clusterId值
			p.attributes.clusterId = cluster.attributes.clusterId;
		},

		/**
		 * @description 创建一个新集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		clusterCreate : function(p) {
			var clusterId = this.clusters.length + 1;
			if (!p.attributes) {
				p.attributes = {};
			}
			p.attributes.clusterId = clusterId;
			//创建一个新集群
			var cluster = {
				"x" : p.x,
				"y" : p.y,
				"attributes" : {
					"clusterCount" : 1,
					"clusterId" : clusterId,
					"extent" : [ p.x, p.y, p.x, p.y ]
				}
			};
			this.clusters.push(cluster);
		},

		/**
		 * @description 显示所有集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		showAllClusters : function() {
			var array = this.groupData();
			for (var i = 0; i <this.clusters.length; i++) {
				var c = this.clusters[i];
				if(c.attributes.clusterCount > array[0]){
					this.singleSym = this.symbolArray[0];
				}else if(c.attributes.clusterCount > array[1]){
					this.singleSym = this.symbolArray[1];
				}else{
					this.singleSym = this.symbolArray[2];
				}
				this.showCluster(c);
			}
		},
		/**
		 * @description 获取分组组值数组
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		groupData:function(){
			//获取最大最小值
			var max = this.clusters[0].attributes.clusterCount;
			var min = this.clusters[0].attributes.clusterCount;
			for (var i = 0; i <this.clusters.length; i++) {
				var count = this.clusters[i].attributes.clusterCount;
				if(max < count)
					max = count;
				else if(min > count)
					min = count;
			}
			//组距
			var dValue = (max - min)/3;
			return [(max - dValue),(min + dValue)];
		},
		/**
		 * @description 显示集群
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		showCluster : function(c) {
			var point = new Point(c.x, c.y,
					this.spatialReference);
			if(this.singleSym == null)
				this.singleSym = new SimpleMarkerSymbol("circle", 20, null, new Color("red"));
			//添加点图形
			this.add(new Graphic(point, this.singleSym,c.attributes));
			//添加文字到指定位置
			var label = new TextSymbol(c.attributes.clusterCount.toString())
			label.color = new Color(this.labelColor);
			label.xoffset = 0;
			label.yoffset = this.labelOffset;
			this.add(new Graphic(point, label,c.attributes));
		},
		/**
		 * @description 添加单个点
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		addSingles : function(singles) {
			//添加单个点到地图上
			arrayUtils.forEach(singles, function(p) {
				var g = new Graphic(new Point(p.x, p.y,this.spatialReference),this.graphicSym, p.attributes,this.singleTemplate);
				this.singles.push(g);
				if (this.showSingles) {
					this.add(g);
				}
			}, this);
		},

		/**
		 * @description 更新集群图形
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		updateClusterGeometry : function(c) {
			var cg = arrayUtils.filter(this.graphics,function(g) {
				return !g.symbol && g.attributes.clusterId == c.attributes.clusterId;
			});
			if (cg.length == 1) {
				cg[0].geometry.update(c.x, c.y);
			} else {
				console.log("didn't find exactly one cluster geometry to update: ",cg);
			}
		},
		/**
		 * @description 更新集群Label
		 * @creator wpz
		 * @createtime 2018-02-06
		 */
		updateLabel : function(c) {
			//找到已存在的集群label
			var label = arrayUtils.filter(this.graphics,function(g) {
				return g.symbol && g.symbol.declaredClass == "esri.symbol.TextSymbol" && g.attributes.clusterId == c.attributes.clusterId;
			});
			if (label.length == 1) {
				//更新集群Label
				this.remove(label[0]);
				var newLabel = new TextSymbol(c.attributes.clusterCount);
				newLabel.color = new Color(this.labelColor);
				newLabel.xoffset = 0;
				newLabel.yoffset = this.labelOffset;
				this.add(new Graphic(new Point(c.x,c.y, this.spatialReference), newLabel, c.attributes));
			} else {
				console.log("didn't find exactly one label: ",label);
			}
		}

	});
})                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
posted @ 2018-05-27 20:31  HPUGIS  阅读(2556)  评论(0编辑  收藏  举报