需求分析
最近项目需求把arcgis for js 4改为3,遇到了一个问题,就是点聚合的效果,3不像4有自带属性配置,因为arcgis for js 3版本没有自带的点聚合效果,所以使用的是ClusterLayer这个额外图层,实现大量点的聚合效果,提升页面的流畅度。这是实现效果
代码实现
- 先去官网下载一个ClusterLayer.js文件,一般引入是没有这个文件,如果有的话,就不需要下载了;
官方实例:https://developers.arcgis.com/javascript/3/samples/layers_point_clustering/
ClusterLayer下载地址:https://developers.arcgis.com/javascript/3/samples/layers_point_clustering/
下载完成之后,需要将文件放在arcgis for js引入的组件中,并且在代码中引入
- 代码实现
核心代码
//你的点数据
let list = [{jd,wd,xxx},{jd,wd,xxx},{jd,wd,xxx},{jd,wd,xxx}]
let datas = []
//格式化数据
var wgs = new SpatialReference({"wkid": 4326});
for (const data of list){
var latlng = new Point(parseFloat(data.jd), parseFloat(data.wd), wgs);
var webMercator = webMercatorUtils.geographicToWebMercator(latlng);
var attributes = data.xxx ;//自定义attributes 数据
//返回的数据格式
datas.push({
"x": webMercator.x,
"y": webMercator.y,
"attributes": attributes
})
}
let clusterLayer = new ClusterLayer({
"data": datas,//点数据
"distance": 100,//点之间的距离(像素)是否显示聚合的距离,比如两个点之间大于100就不聚合了
"id": "clusters",
"labelColor": "#fff",
"labelOffset": 10,
"resolution": map.extent.getWidth() / map.width,
"singleColor": "#888",
//"singleTemplate": popupTemplate//气泡信息,关于点击方法和移入移出显示气泡,最好后期自定义
});
//控制聚合的(不用管)
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);
map.addLayer(clusterLayer);
以上代码不可以直接运行,主要是用来理解
- 一下是官方文档的实例,把ClusterLayer引入后可以直接运行(做了少许修改)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Cluster</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.45/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.45/esri/css/esri.css">
<style>
html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
#map{ margin: 0; padding: 0; }
/* center the image in the popup */
.esriViewPopup .gallery { margin: 0 auto !important; }
</style>
<script>
// helpful for understanding dojoConfig.packages vs. dojoConfig.paths:
// http://www.sitepen.com/blog/2013/06/20/dojo-faq-what-is-the-difference-packages-vs-paths-vs-aliases/
var dojoConfig = {
paths: {
extras: location.pathname.replace(/\/[^/]+$/, "") + "/extras"
}
};
</script>
<script src="https://js.arcgis.com/3.45/"></script>
<script>
var map;
require([
"dojo/parser",
"dojo/ready",
"dojo/_base/array",
"esri/Color",
"dojo/dom-style",
"dojo/query",
"esri/map",
"esri/request",
"esri/graphic",
"esri/geometry/Extent",
"esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/PictureMarkerSymbol",
"esri/renderers/ClassBreaksRenderer",
"esri/layers/GraphicsLayer",
"esri/SpatialReference",
"esri/dijit/PopupTemplate",
"esri/geometry/Point",
"esri/geometry/webMercatorUtils",
"extras/ClusterLayer",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
parser, ready, arrayUtils, Color, domStyle, query,
Map, esriRequest, Graphic, Extent,
SimpleMarkerSymbol, SimpleFillSymbol, PictureMarkerSymbol, ClassBreaksRenderer,
GraphicsLayer, SpatialReference, PopupTemplate, Point, webMercatorUtils,
ClusterLayer
) {
ready(function() {
parser.parse();
var clusterLayer;
var popupOptions = {
"markerSymbol": new SimpleMarkerSymbol("circle", 20, null, new Color([0, 0, 0, 0.25])),
"marginLeft": "20",
"marginTop": "20"
};
map = new Map("map", {
basemap: "oceans",
center: [-117.789, 33.543],
zoom: 13
});
map.on("load", function() {
// hide the popup's ZoomTo link as it doesn't make sense for cluster features
domStyle.set(query("a.action.zoomTo")[0], "display", "none");
// get the latest 1000 photos from instagram/laguna beach
var photos = esriRequest({
url: "https://developers.arcgis.com/javascript/3/samples/layers_point_clustering/data/1000-photos.json",
handleAs: "json"
});
photos.then(addClusters, error);
});
function addClusters(resp) {
var photoInfo = {};
var wgs = new SpatialReference({
"wkid": 4326
});
photoInfo.data = arrayUtils.map(resp, function(p) {
var latlng = new Point(parseFloat(p.lng), parseFloat(p.lat), wgs);
var webMercator = webMercatorUtils.geographicToWebMercator(latlng);
var attributes = {
"Caption": p.caption,
"Name": p.full_name,
"Image": p.image,
"Link": p.link
};
return {
"x": webMercator.x,
"y": webMercator.y,
"attributes": attributes
};
});
// popupTemplate to work with attributes specific to this dataset
var popupTemplate = new PopupTemplate({
"title": "",
"fieldInfos": [{
"fieldName": "Caption",
visible: true
}, {
"fieldName": "Name",
"label": "By",
visible: true
}, {
"fieldName": "Link",
"label": "On Instagram",
visible: true
}]
});
// cluster layer that uses OpenLayers style clustering
clusterLayer = new ClusterLayer({
"data": photoInfo.data,
"distance": 100,
"id": "clusters",
"labelColor": "#fff",
"labelOffset": 10,
"resolution": map.extent.getWidth() / map.width,
"singleColor": "#888",
"singleTemplate": popupTemplate
});
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);
map.addLayer(clusterLayer);
// close the info window when the map is clicked
map.on("click", cleanUp);
// close the info window when esc is pressed
map.on("key-down", function(e) {
if (e.keyCode === 27) {
cleanUp();
}
});
}
function cleanUp() {
map.infoWindow.hide();
clusterLayer.clearSingles();
}
function error(err) {
console.log("something failed: ", err);
}
// show cluster extents...
// never called directly but useful from the console
window.showExtents = function() {
var extents = map.getLayer("clusterExtents");
if ( extents ) {
map.removeLayer(extents);
}
extents = new GraphicsLayer({ id: "clusterExtents" });
var sym = new SimpleFillSymbol().setColor(new Color([205, 193, 197, 0.5]));
arrayUtils.forEach(clusterLayer._clusters, function(c, idx) {
var e = c.attributes.extent;
extents.add(new Graphic(new Extent(e[0], e[1], e[2], e[3], map.spatialReference), sym));
}, this);
map.addLayer(extents, 0);
};
});
});
</script>
</head>
<body>
<div data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'headline',gutters:false"
style="width: 100%; height: 100%; margin: 0;">
<div id="map"
data-dojo-type="dijit/layout/ContentPane"
data-dojo-props="region:'center'">
</div>
</div>
</body>
</html>
有时间的话会出一个自定义的聚合, 如果帮助到大家,求赞求转发!!