-
首先官方也給出了例子 但是這不能滿足我們的需求image.png
改造后 當(dāng)然設(shè)置了他的 renderer 達(dá)到效果
ss.png
define([
"dojo/_base/declare",
"dojo/_base/array",
"esri/Color",
"dojo/_base/connect",
"esri/SpatialReference",
"esri/geometry/Point",
"esri/graphic",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/TextSymbol",
"esri/dijit/PopupTemplate",
"esri/layers/GraphicsLayer",
"esri/InfoTemplate",
"esri/geometry/Extent",
"dojo/dom-construct",
"esri/symbols/PictureMarkerSymbol",
"esri/dijit/InfoWindow"
], function(
declare, arrayUtils, Color, connect,
SpatialReference, Point, Graphic, SimpleMarkerSymbol, TextSymbol,
PopupTemplate, GraphicsLayer,
InfoTemplate,
Extent,
domConstruct,PictureMarkerSymbol,
InfoWindow
) {
return declare([GraphicsLayer], {
constructor: function(options) {
this._clusterTolerance = options.distance || 50;
// 頁面初始數(shù)據(jù)
this._clusterData = options.data || [];
//
this._clusters = [];
this._clusterLabelColor = options.labelColor || "#000";
// 標(biāo)簽偏移可以是零,所以處理方式不同
this._clusterLabelOffset = (options.hasOwnProperty("labelOffset")) ? options.labelOffset : -5;
this._singles = []; // 在單擊圖形時填充
this._showSingles = options.hasOwnProperty("showSingles") ? options.showSingles : true;
// 表示單個點的圖形
var SMS = SimpleMarkerSymbol;
this._singleSym = options.singleSymbol || new SMS("circle", 3, null, new Color("#097"));
this._singleTemplate = options.singleTemplate || new InfoTemplate("Attributes", "{*}");
this._maxSingles = options.maxSingles || 1000;
this._webmap = options.hasOwnProperty("webmap") ? options.webmap : false;
this._sr = options.spatialReference || new SpatialReference({
"wkid": 4326
});
this._zoomEnd = null;
this._mapclick = null;
},
// override esri/layers/GraphicsLayer methods
_setMap: function(map, surface) {
// 計算并設(shè)置初始分辨率
this._clusterResolution = map.extent.getWidth() / map.width; // probably a bad default...
if(this._zoomEnd==null){this._clusterGraphics();}
// 連接到onZoomEnd,以便在縮放級別更改時重新聚集數(shù)據(jù)
this._zoomEnd = connect.connect(map, "onZoomEnd", this, function() {
// 更新分辨率
this._clusterResolution = this._map.extent.getWidth() / this._map.width;
this.clear();
this._clusterGraphics();
});
// GraphicsLayer將在這里添加自己的偵聽器
var div = this.inherited(arguments);
return div;
},
_unsetMap: function() {
this.inherited(arguments);
connect.disconnect(this._zoomEnd);
},
// 公共ClusterLayer方法
add: function(p) {
//參數(shù)是要添加到現(xiàn)有集群中的數(shù)據(jù)點。如果數(shù)據(jù)點落在現(xiàn)有集群內(nèi),
// 則將其添加到該集群,并更新集群的標(biāo)簽。如果新點不在現(xiàn)有集群中,則創(chuàng)建一個新集群
// 如果傳遞了一個圖形,使用GraphicsLayer的add方法
if (p.declaredClass) {
this.inherited(arguments);
return;
}
// 將新數(shù)據(jù)添加到_clusterData中,以便將其包含在集群中
this._clusterData.push(p);
var clustered = false;
// 當(dāng)?shù)貓D級別改變時
// 在現(xiàn)有集群中查找新點
for (var i = 0; i < this._clusters.length; i++) {
var c = this._clusters[i];
// 將該點添加到現(xiàn)有集群
this._clusterAddPoint(p, c);
// 更新集群的幾何形狀
this._updateClusterGeometry(c);
// 更新標(biāo)簽
this._updateLabel(c);
clustered = true;
}
if (!clustered) {
p.attributes.clusterCount = 1;
this._clusterCreate(p);
this._showCluster(p);
}
},
showSingles: function() {
var singles = [];
for (var i = 0, il = this._clusterData.length; i < il; i++) {
singles.push(this._clusterData[i]);
}
this._addSingles(singles);
},
clear: function() {
// 摘要:刪除所有集群和數(shù)據(jù)點
this.inherited(arguments);
this._clusters.length = 0;
},
clearSingles: function(singles) {
// 摘要:刪除表示單個數(shù)據(jù)點的圖形。
var s = singles || this._singles;
arrayUtils.forEach(s, function(g) {
this.remove(g);
}, this);
this._singles.length = 0;
},
onClick: function(e) {
// 刪除任何以前顯示的單一功能
this._map.infoWindow.resize(440, 350)
this.clearSingles(this._singles);
// 查找組成被單擊的集群的單個圖形
// would be nice to use filter but performance tanks with large arrays in IE
var singles = [];
for (var i = 0, il = this._clusterData.length; i < il; i++) {
if (e.graphic.attributes.clusterId == this._clusterData[i].attributes.clusterId) {
singles.push(this._clusterData[i]);
}
}
if (singles.length > this._maxSingles) {
alert("Sorry, that cluster contains more than " + this._maxSingles + " points. Zoom in for more detail.");
return;
} else {
e.stopPropagation();
// 停止從彈出到地圖的單擊
if (singles.length == 1) {
// 單一的時候
// this._map.infoWindow.show(e.graphic.geometry);
// this._graphicOnClick(e.graphic.attributes);
this._graphicOnClick(e);
} else if(this._map.getMaxZoom()-this._map.getZoom()>2 && singles.length > 1){
//點擊singles時得到符號的extent 然后設(shè)置為當(dāng)前可見范圍 放大地圖 達(dá)到放大地圖等級 觸發(fā)重新渲染點 從而分開點
var xmax, ymax, xmin, ymin;
xmax = this._find(singles, "x", "max");
ymax = this._find(singles, "y", "max");
xmin = this._find(singles, "x", "min");
ymin = this._find(singles, "y", "min");
var extent = new Extent(xmin, ymin, xmax, ymax, this._sr)
this._map.setExtent(extent);
this._clusterResolution = this._map.extent.getWidth() / this._map.width;
this.clear();
this._clusterGraphics();
this._addSingles(singles);
}
}
},
//如果點前是一個點 則觸發(fā)此事件
_graphicOnClick: function(e) {
var _this = this;
var id;
if (e.graphic.attributes.id.id) {
id = e.graphic.attributes.id.id;
} else {
id = e.graphic.attributes.id;
}
this.addInfo(id, function(res) {
// var node = domConstruct.create("div", {
// innerHTML: "<div class='content_doms'>" +
// "<div class='content_doms_header'>" +
// "<table class='table table-bordered table-condensed'><thead><tr class='info'><th>戶主姓名</th><th>所在自然村</th><th>本戶人數(shù)</th><th>聯(lián)系電話</th></tr></thead>" +
// "<tbody><tr><td>" + res.nhFarmerInfo.name + "</td><td>" + res.nhFarmerInfo.naturalvillagename +
// "</td><td>" + res.nhFarmerInfo.peoples + "</td><td>" + res.nhFarmerInfo.telephone +
// "</td></tr></tbody></table>" +
// "</div>" +
// "<div class='content_doms_footer'>" + _this.createList(res.nhOutletList) + "<div>" +
// "</div>"
// });
// 表格生成代碼
var node = domConstruct.create("div", {
innerHTML: "<div class='content_doms'>" +
"<div class='content_doms_header'>" +
// <table class='table table-bordered table-condensed'>" + createTableList(res.nhFarmerInfo) +"</table>
generateTable(res.nhFarmerInfo,2)+
"</div>" +
"<div class='content_doms_footer'>" +createList(res.nhOutletList) + "<div>" +
"</div>"
});
// var infoTemplate = new InfoTemplate("農(nóng)戶信息", node);
// 排口信息
res.id = id;
// e.graphic.setAttributes(res);
// e.graphic.setInfoTemplate(infoTemplate);
_this._map.infoWindow.setTitle("農(nóng)戶信息");
_this._map.infoWindow.setContent(node);
_this._map.infoWindow.show(e.graphic.geometry);
});
},
// 查找數(shù)組中最大值 或者 最小值
_find: function(arr, pro, single) {
return Math[single].apply(Math, arr.map(function(o) {
return o[pro]
}))
},
addInfo: function(id, cb) {
var url ='/hbnhcj/farmer/nhFarmerInfo/getFarmerWithOutlet';
$ajax(url,"GET",{id:id},function(data){
cb(data.result)
});
},
// 內(nèi)部方法 ***************************起點*********************************
_clusterGraphics: function() {
// ,遍歷這些點
for (var j = 0, jl = this._clusterData.length; j < jl; j++) {
// 查看當(dāng)前特性是否應(yīng)該添加到集群中
var point = this._clusterData[j];
var clustered = false;
var numClusters = this._clusters.length;
for (var i = 0; i < this._clusters.length; i++) {
// 當(dāng)前集群
var c = this._clusters[i];
// 查看是否滿足距離公式
if (this._clusterTest(point, c)) {
// 如果滿足 就將當(dāng)前點添加到
this._clusterAddPoint(point, c);
clustered = true;
break;
}
}
if (!clustered) {
this._clusterCreate(point);
}
}
this._showAllClusters();
},
_clusterTest: function(p, cluster) {
var distance = (
Math.sqrt(
Math.pow((cluster.x - p.x), 2) + Math.pow((cluster.y - p.y), 2)
) / this._clusterResolution
);
return (distance <= this._clusterTolerance);
},
// 應(yīng)該包括傳遞給clusterAddPoint的點
//在現(xiàn)有集群中
//還為該點提供一個名為clusterId的屬性
//這與它的星系團(tuán)相對應(yīng)
_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;
//構(gòu)建一個包括集群中所有點的范圍
//擴(kuò)展只用于調(diào)試/測試…該層不使用
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;
}
// 增加數(shù)
cluster.attributes.clusterCount++;
// 屬性可能不存在
if (!p.hasOwnProperty("attributes")) {
p.attributes = {};
}
// 給圖形一個集群id
p.attributes.clusterId = cluster.attributes.clusterId;
},
//傳遞給clusterCreate的點不在
//為層指定的聚類距離
//為它創(chuàng)建一個新的集群
_clusterCreate: function(p) {
var clusterId = this._clusters.length + 1;
// console.log("cluster create, id is: ", clusterId);
// p.attributes might be undefined
//控制臺。日志(“集群創(chuàng)建,id是:”,clusterId);
// p。屬性可能未定義
if (!p.attributes) {
p.attributes = {};
}
p.attributes.clusterId = clusterId;
// 創(chuàng)建集群
var cluster = {
"x": p.x,
"y": p.y,
"attributes": {
"clusterCount": 1,
"clusterId": clusterId,
"id": p.attributes,
"extent": [p.x, p.y, p.x, p.y]
}
};
this._clusters.push(cluster);
},
// 展示所有聚類
_showAllClusters: function() {
for (var i = 0, il = this._clusters.length; i < il; i++) {
var c = this._clusters[i];
this._showCluster(c);
}
},
// 展示單一聚類
_showCluster: function(c) {
// 單一集群
console.log(c);
var point = new Point(c.x, c.y, this._sr);
this.add(
new Graphic(
point,
null,
c.attributes
)
);
// 下面的代碼用于不使用單點標(biāo)記集群
if (c.attributes.clusterCount == 1) {
return;
}
// show number of points in the cluster
// 顯示集群中的點的數(shù)量
var label = new TextSymbol(c.attributes.clusterCount.toString())
.setColor(new Color(this._clusterLabelColor))
.setOffset(0, this._clusterLabelOffset);
this.add(
new Graphic(
point,
label,
c.attributes
)
);
},
_addSingles: function(singles) {
// 向地圖添加單個圖形
arrayUtils.forEach(singles, function(p) {
var g = new Graphic(
new Point(p.x, p.y, this._sr),
new PictureMarkerSymbol("https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32)
.setOffset(0, 15),
p.attributes,
this._singleTemplate
);
this._singles.push(g);
if (this._showSingles) {
this.add(g);
}
}, this);
// this._map.infoWindow.show
// this._map.infoWindow.setFeatures(this._singles);
},
_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);
}
},
_updateLabel: function(c) {
// 查找現(xiàn)有的標(biāo)簽
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) {
// console.log("update label...found: ", label);
this.remove(label[0]);
var newLabel = new TextSymbol(c.attributes.clusterCount)
.setColor(new Color(this._clusterLabelColor))
.setOffset(0, this._clusterLabelOffset);
this.add(
new Graphic(
new Point(c.x, c.y, this._sr),
newLabel,
c.attributes
)
);
// console.log("updated the label");
} else {
console.log("didn't find exactly one label: ", label);
}
},
// debug only...never called by the layer 調(diào)試只有……從未被層調(diào)用
_clusterMeta: function() {
// 打印總功能數(shù)
console.log("Total: ", this._clusterData.length);
// 加起來并打印出來
var count = 0;
arrayUtils.forEach(this._clusters, function(c) {
count += c.attributes.clusterCount;
});
console.log("In clusters: ", count);
}
});
});
- 外部使用
loadClusterLayer: function(data,map) {
var photoInfo = {},
clusterLayer;
var wgs = new SpatialReference({
"wkid": 4326
});
photoInfo.data = array.map(data, function(p) {
var latlng = new Point(parseFloat(p.lon), parseFloat(p.lat), wgs);
// 轉(zhuǎn)成webMercator坐標(biāo)系
// var webMercator = webMercatorUtils.geographicToWebMercator(latlng);
var attributes = {
"id": p.id
};
return {
"x": latlng.x,
"y": latlng.y,
"attributes": attributes
};
});
var one = new PictureMarkerSymbol("https://static.arcgis.com/images/Symbols/Shapes/BluePin1LargeB.png", 32, 32)
.setOffset(0, 15);
// cluster layer that uses OpenLayers style clustering
clusterLayer = new ClusterLayer({
"data": photoInfo.data,
"distance": 1,
"id": "clusters",
"labelColor": "#000",
"labelOffset": -5,
"resolution": map.extent.getWidth() / map.width,
"singleColor": "#888",
"singleTemplate": '',
"spatialReference": wgs,
});
var defaultSym = new SimpleMarkerSymbol().setSize(4);
var renderer = new ClassBreaksRenderer(defaultSym, "clusterCount");
var first = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 50,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 125, 3, 0.2]), 10),
new Color([241, 128, 23, 0.9]));
var second = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 35,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([241, 211, 87, 0.6]), 10),
new Color([240, 194, 13, 0.9]));
var third = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 25,
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([181, 226, 140, 0.6]), 10),
new Color([110, 204, 57, 0.9]));
//渲染等級
renderer.addBreak(0, 1, one);
renderer.addBreak(2, 3, third);
renderer.addBreak(4, 20, second);
renderer.addBreak(21, 100, first);
clusterLayer.setRenderer(renderer);
return clusterLayer
}
添加到地圖
//調(diào)取api 獲取要渲染的點
this._loadData("460000", 1, 100000, function(data) {
// 采集信息
layer = this.loadClusterLayer(data,map);
layer.setVisibility(layerConfig.visible);
map.addLayer(layer);
})
- 要點
通過設(shè)置distance大小改變兩個點的聚合和距離
在引入這個寫好的圖層類的時候?qū)⑵浞湃肱c根目錄同級 代碼引入
"extras/ClusterLayer",
若你是gis 完整的項目 需要在init.js 設(shè)置dojoConfig
dojoConfig = {
parseOnLoad: false,
async: true,
tlmSiblingOfDojo: false,
has: {
'extend-esri': 1
},
paths: {
//我放到了我的項目的根目錄下了 若放在服務(wù)器根目錄下就改為/extras
extras:"../extras"
}
};

sss (2).png

