This sample demonstrates how to enable clustering on a FeatureLayer and aggregate numeric attributes to use in a custom cluster renderer. This app aggregates car crash data into clusters and styles each cluster with a red color if it includes at least one fatality. Clusters with no fatalities are colored beige.
Clustering is a method of aggregating features in a FeatureLayer, CSVLayer, GeoJSONLayer, WFSLayer, or OGCFeatureLayer by grouping them in clusters defined by screen space.
Aggregate fields are defined in the fields property of the FeatureReductionCluster class. Once defined, these fields may be used in the renderer, labels, and popup of the clusters.
The lines highlighted in green in the snippet below show how aggregate fields are defined. Lines highlighted in blue show where these fields are used.
const clusterConfig = {
type: "cluster",
fields: [
new AggregateField({
name: "aggregateCount",
statisticType: "count"
}),
new AggregateField({
name: "SUM_PERSONS_INJURED",
onStatisticField: "NUMBER_OF_PERSONS_INJURED",
statisticType: "sum"
}),
new AggregateField({
name: "SUM_PEDESTRIANS_INJURED",
onStatisticField: "NUMBER_OF_PEDESTRIANS_INJURED",
statisticType: "sum"
}),
new AggregateField({
name: "SUM_CYCLIST_INJURED",
onStatisticField: "NUMBER_OF_CYCLIST_INJURED",
statisticType: "sum"
}),
new AggregateField({
name: "SUM_MOTORIST_INJURED",
onStatisticField: "NUMBER_OF_MOTORIST_INJURED",
statisticType: "sum"
}),
new AggregateField({
name: "AVG_MOTORIST_INJURED",
onStatisticField: "NUMBER_OF_MOTORIST_INJURED",
statisticType: "avg"
}),
new AggregateField({
name: "SUM_KILLED",
onStatisticField: "NUMBER_OF_PERSONS_KILLED",
statisticType: "sum"
})
],
renderer: {
type: "class-breaks",
field: "SUM_KILLED",
legendOptions: {
title: "Car crashes"
},
classBreakInfos: [
{
minValue: 0,
maxValue: 0,
label: "No fatalities",
symbol: {
type: "simple-marker",
color: excludedColor,
outline: null,
outline: {
color: "rgba(153, 31, 23, 0.3)",
width: 0.3
}
}
}, {
minValue: 1,
maxValue: 99999999999,
label: "Includes fatalities",
symbol: {
type: "simple-marker",
color: includedColor,
outline: {
color: "rgba(153, 31, 23, 0.3)",
width: 0.3
}
}
}
]
},
clusterRadius: "100px",
popupTemplate: {
title: "Crash summary",
content: [
{
type: "text",
text: "{aggregateCount} car crashes occurred in this area, including {SUM_KILLED} fatalities."
},
{
type: "fields",
fieldInfos: [
{
fieldName: "aggregateCount",
label: "Total crashes",
format: {
places: 0,
digitSeparator: true
}
},
{
fieldName: "SUM_PERSONS_INJURED",
label: "Total injured",
format: {
places: 0,
digitSeparator: true
}
},
{
fieldName: "SUM_PEDESTRIANS_INJURED",
label: "Pedestrians injured"
},
{
fieldName: "SUM_CYCLIST_INJURED",
label: "Cyclists injured"
},
{
fieldName: "SUM_MOTORIST_INJURED",
label: "Motorists injured"
},
{
fieldName: "SUM_KILLED",
label: "Total killed"
}
]
}
]
},
clusterMinSize: "24px",
clusterMaxSize: "60px",
labelingInfo: [
{
deconflictionStrategy: "none",
labelExpressionInfo: {
expression: `
var label = Text($feature.aggregateCount, '#,###');
var fatalities = $feature.SUM_KILLED;
if(fatalities > 0){
label += \`\n(\${fatalities})\`
}
return label;
`
},
symbol: {
type: "text",
color: "white",
font: {
weight: "bold",
family: "Noto Sans",
size: "12px"
},
haloColor: includedColor,
haloSize: 1
},
labelPlacement: "center-center"
}
]
};
Related samples and resources
![Image preview of related sample Intro to clustering](/javascript/latest/static/fc479d6273a98b010ce55c0034e30750/e1e8c/thumbnail.png)
Intro to clustering
Intro to clustering
![Image preview of related sample Override cluster symbol](/javascript/latest/static/f991fa54f9cf3904190baa615b1d482e/e1e8c/thumbnail.png)
Override cluster symbol
Override cluster symbol
![Image preview of related sample Cluster size based on the sum of a field](/javascript/latest/static/8f531a7afafe18d144f9d4e51db11ed2/e1e8c/thumbnail.png)
Cluster size based on the sum of a field
Cluster size based on the sum of a field
![Image preview of related sample Clustering - filter popup features](/javascript/latest/static/50c3b5a936aeddb3db0980f744644a95/e1e8c/thumbnail.png)
Clustering - filter popup features
This sample demonstrates how to filter clustered features within a cluster's popup.
![Image preview of related sample Clustering - generate suggested configuration](/javascript/latest/static/eb2d6a44bde5b4170a6b1de2acce859a/e1e8c/thumbnail.png)
Clustering - generate suggested configuration
Clustering - generate suggested configuration
![Image preview of related sample Clustering - query clusters](/javascript/latest/static/6a49a67d1dfec5d8acef4fda7b62505e/e1e8c/thumbnail.png)
Clustering - query clusters
Clustering - query clusters
![Image preview of related sample Clustering - advanced configuration](/javascript/latest/static/8e49434dce56044812132546eb376276/e1e8c/thumbnail.png)
Clustering - advanced configuration
Clustering - advanced configuration
![Image preview of related sample Popup charts for clusters](/javascript/latest/static/50c3b5a936aeddb3db0980f744644a95/e1e8c/thumbnail.png)
Popup charts for clusters
This sample demonstrates how to summarize clustered features using charts within a cluster's popup.
![Image preview of related sample Clustering with visual variables](/javascript/latest/static/15d49bba0ce0db75b5c138f7a8a5f7cf/e1e8c/thumbnail.png)
Clustering with visual variables
Clustering with visual variables
FeatureReductionCluster
Read the Core API Reference for more information.