Skip to content

This sample demonstrates how to enable binning on a FeatureLayer and aggregate numeric attributes to use in the renderer, popupTemplate and labels of the bins.

Binning is a method of aggregating features in a FeatureLayer, CSVLayer, GeoJSONLayer, WFSLayer, or OGCFeatureLayer by grouping them to predefined bins. Bins are generated using geohashes.

Aggregate fields are defined in the fields property of the FeatureReductionBinning class. Once defined, these fields may be used in the renderer, labels, and popup of the bins. 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.

Define aggregate fields
const featureReduction = {
type: "binning",
fixedBinLevel: 6,
fields: [
new AggregateField({
name: "aggregateCount",
statisticType: "count",
}),
new AggregateField({
name: "SUM_PERSONS_INJURED",
alias: "Total number of persons injured",
onStatisticField: "NUMBER_OF_PERSONS_INJURED",
statisticType: "sum",
}),
new AggregateField({
name: "SUM_PEDESTRIANS_INJURED",
alias: "Number of pedestrians injured",
onStatisticField: "NUMBER_OF_PEDESTRIANS_INJURED",
statisticType: "sum",
}),
new AggregateField({
name: "SUM_CYCLIST_INJURED",
alias: "Number of cyclists injured",
onStatisticField: "NUMBER_OF_CYCLIST_INJURED",
statisticType: "sum",
}),
new AggregateField({
name: "SUM_MOTORIST_INJURED",
alias: "Number of cyclists injured",
onStatisticField: "NUMBER_OF_MOTORIST_INJURED",
statisticType: "sum",
}),
new AggregateField({
name: "AVG_MOTORIST_INJURED",
alias: "Ratio of motorist injuries to crashes",
onStatisticField: "NUMBER_OF_MOTORIST_INJURED",
statisticType: "avg",
}),
new AggregateField({
name: "SUM_KILLED",
alias: "Total fatalities",
onStatisticField: "NUMBER_OF_PERSONS_KILLED",
statisticType: "sum",
}),
],
labelsVisible: true,
labelingInfo: [
new LabelClass({
minScale: 36112,
maxScale: 0,
deconflictionStrategy: "none",
symbol: {
type: "text", // autocasts as new TextSymbol()
color: "white",
font: {
family: "Noto Sans",
size: 12,
weight: "bold",
},
haloColor: colors[4],
haloSize: 0.5,
},
labelExpressionInfo: {
expression: "Text($feature.AVG_MOTORIST_INJURED, '#%')",
},
}),
],
fieldConfigurations: [
{
name: "aggregateCount",
fieldFormat: {
type: "number",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
useGrouping: "always",
},
},
{
name: "SUM_PERSONS_INJURED",
fieldFormat: {
type: "number",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
useGrouping: "never",
},
},
],
popupEnabled: true,
popupTemplate: {
title: "Crash summary",
content: [
{
type: "text",
text: "{aggregateCount} car crashes occurred in this area.",
},
{
type: "fields",
fieldInfos: [
{
fieldName: "aggregateCount",
},
{
fieldName: "SUM_PERSONS_INJURED",
},
{
fieldName: "SUM_PEDESTRIANS_INJURED",
},
{
fieldName: "SUM_CYCLIST_INJURED",
},
{
fieldName: "SUM_MOTORIST_INJURED",
},
{
fieldName: "SUM_KILLED",
},
],
},
],
},
renderer: {
type: "simple",
symbol: {
type: "simple-marker",
color: [0, 255, 71, 1],
outline: null,
outline: {
color: "rgba(153, 31, 23, 0.3)",
width: 0.3,
},
},
visualVariables: [
{
type: "size",
field: "aggregateCount",
legendOptions: {
title: "Total crashes",
},
minSize: {
type: "size",
valueExpression: "$view.scale",
stops: [
{ value: 18055, size: 18 },
{ value: 36111, size: 12 },
{ value: 72223, size: 8 },
{ value: 144447, size: 4 },
{ value: 288895, size: 2 },
{ value: 577790, size: 1 },
],
},
maxSize: {
type: "size",
valueExpression: "$view.scale",
stops: [
{ value: 18055, size: 48 },
{ value: 36111, size: 32 },
{ value: 72223, size: 24 },
{ value: 144447, size: 18 },
{ value: 288895, size: 12 },
{ value: 577790, size: 6 },
],
},
minDataValue: 10,
maxDataValue: 300,
},
{
type: "color",
field: "AVG_MOTORIST_INJURED",
legendOptions: {
title: "% of motorists injured per crash",
},
stops: [
{ value: 0, color: colors[0], label: "No injuries" },
{ value: 0.1, color: colors[1] },
{ value: 0.3, color: colors[2], label: "30%" },
{ value: 0.5, color: colors[3] },
{ value: 0.75, color: colors[4], label: ">75%" },
],
},
],
},
};