在arcgis api for js中有一个clusterlayer,可以实现点聚合显示,以解决点过于密集导致的视觉效果差。clusterLayer是重写的graphicLayer。官方demo效果如下:
如果我们要将该方法应用到项目中,显然仅有官方demo效果是不够的,需要根据自己的需求来进行修改。
1.聚合距离修改。
可通过修改“distance” 属性实现。
2.聚合图形修改
聚合图形其实是根据聚合点个数clustercount来进行分类渲染,在官网示例中表现为红绿蓝泡泡图形。
var defaultSym = new SimpleMarkerSymbol().setSize(4);
var renderer = new ClassBreaksRenderer(defaultSym, "clusterCount");
var picBaseUrl = "https://static.arcgis.com/images/Symbols/Shapes/";
var blue = new PictureMarkerSymbol(picBaseUrl + "BluePin1LargeB.png", 32, 32).setOffset(0, 15);
var green = new PictureMarkerSymbol(picBaseUrl + "GreenPin1LargeB.png", 64, 64).setOffset(0, 15);
var red = new PictureMarkerSymbol(picBaseUrl + "RedPin1LargeB.png", 72, 72).setOffset(0, 15);
renderer.addBreak(0, 2, blue);
renderer.addBreak(2, 200, green);
renderer.addBreak(200, 1001, red);
clusterLayer.setRenderer(renderer);
以上是官方代码,可修改成自己的聚合符号。 如下
var defaultSym = new SimpleMarkerSymbol().setSize(10);
var renderer = new ClassBreaksRenderer( defaultSym,"clusterCount");
var blue = new PictureMarkerSymbol( "../../../imgs/domain/blue.png", 32, 32).setOffset(0, 15);
var green = new PictureMarkerSymbol("../../../imgs/domain/green.png", 64, 64).setOffset(0, 15);
var red = new PictureMarkerSymbol("../../../imgs/domain/red.png", 72, 72).setOffset(0, 15);
renderer.addBreak(0,20 , blue);
renderer.addBreak(20, 200, green);
renderer.addBreak(200, 1001, red);
clusterLayer.setRenderer(renderer);
其中defaultSym是在break断层(如果一开始是从2到20的话,那么0到2的渲染符号就是defaultSym)时的渲染图形,也是定义ClassBreaksRenderer必须要有的参数。
3.点击聚合符号显示的单个点符号修改。
_addSingles: function(singles) {
// add single graphics to the map
arrayUtils.forEach(singles, function(p) {
var picSym;
if(p.attributes.装备类型=="火箭"){
picSym = new PictureMarkerSymbol("../../../imgs/domain/hj.png", 28, 18)
}
else if(p.attributes.装备类型=="高炮"){
picSym = new PictureMarkerSymbol("../../../imgs/domain/gp.png", 28, 24)
}
else if(p.attributes.装备类型=="燃烧炉"){
picSym = new PictureMarkerSymbol("../../../imgs/domain/rsl.png", 20, 30)
}
else{
picSym = SimpleMarkerSymbol().setSize(4);
}
var g = new Graphic(
new Point(p.x, p.y, this._sr),
picSym,
p.attributes,
this._singleTemplate
);
this._singles.push(g);
if ( this._showSingles ) {
this.add(g);
}
}, this);
this._map.infoWindow.setFeatures(this._singles);
}
每一个点是一个graphic,根据自己项目的要求,定义单个点的符号。
4.缩放到一定级别时,显示单点
官方代码不论如何缩放将一直显示聚合后的样式,如果想要放大到一定级别显示单个点,可在clusterLayer.js添加一个函数
showSingles:function()
{
var singles = [];
for ( var i = 0, il = this._clusterData.length; i < il; i++) {
singles.push(this._clusterData[i]);
}
this._addSingles(singles);
}
在每次缩放完,地图更新完后判断当前zoom级别,进行后续操作
map.on("update-end", function() {
if(map.getZoom()>=11)
{
map.getLayer("clusters").clear();
map.getLayer("clusters").showSingles();
}
else if(map.getZoom()<11)
{
var defaultSym = new SimpleMarkerSymbol().setSize(10);
var renderer = new ClassBreaksRenderer( defaultSym,"clusterCount");
var blue = new PictureMarkerSymbol( "../../../imgs/domain/blue.png", 32, 32).setOffset(0, 15);
var green = new PictureMarkerSymbol("../../../imgs/domain/green.png", 64, 64).setOffset(0, 15);
var red = new PictureMarkerSymbol("../../../imgs/domain/red.png", 72, 72).setOffset(0, 15);
renderer.addBreak(0,20 , blue);
renderer.addBreak(20, 200, green);
renderer.addBreak(200, 1001, red);
map.getLayer("clusters").setRenderer(renderer);
}
});
5.clusterLayer.js的onclick函数
由于每次点击后,均执行this.clearSingles(this._singles);当放大到显示单点时会带来很多不便,所以考虑要执行清除单点时先进行缩放等级判断。
if(map.getZoom()<11){
this.clearSingles(this._singles);
}
6.clusterLayer的resolution(分辨率)修改
点聚合是根据地图的x轴范围除以屏幕的范围来进行聚合,由于官方地图是平面坐标系,而实际使用中可能使用地理坐标系,所以需要将地图的x轴范围进行转换。
"resolution": map.extent.getWidth() / map.width//原代码
"resolution": (map.extent.xmax*20037508.34/180-map.extent.xmin*20037508.34/180) / map.width//更改后
7.PopupTemplate弹窗
此弹窗为点击地图上的要素弹出的详细信息窗口,可对其进行设置,使其显示图片等信息,由于实际应用中可能会加载数据库中的图片,sourceUrl就需要用到接口,所以不能单纯的仅使用图片地址进行加载。需要将接口写入sourceUrl,如下:
"sourceURL": '/pic?fileName='+'{图片1}',//接口+资源地址进行显示
"linkURL":"../../../views/domain/decision/siteImageDisplay.html"+"?img="+"{图片1}"//点击图片在另一页面查看大图