關於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);
			}
		}

	});
})                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM