From 957e05f38606b5ef987736dc549d5f370ceac15b Mon Sep 17 00:00:00 2001 From: Evan Freethy Date: Tue, 3 Feb 2026 13:31:29 -0800 Subject: [PATCH] Adds zoom as an optional third parameter to the reduce callback --- index.js | 4 ++-- test/test.js | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 4dce8d36..e47c734c 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ const defaultOptions = { generateId: false, // a reduce function for calculating custom cluster properties - reduce: null, // (accumulated, props) => { accumulated.sum += props.sum; } + reduce: null, // (accumulated, props, zoom) => { accumulated.sum += props.sum; } // properties to use for individual points when running the reducer map: props => props // props => ({sum: props.my_value}) @@ -331,7 +331,7 @@ export default class Supercluster { clusterPropIndex = this.clusterProps.length; this.clusterProps.push(clusterProperties); } - reduce(clusterProperties, this._map(data, k)); + reduce(clusterProperties, this._map(data, k), zoom); } } diff --git a/test/test.js b/test/test.js index 5fb05107..1ea4db24 100644 --- a/test/test.js +++ b/test/test.js @@ -95,6 +95,31 @@ test('aggregates cluster properties with reduce', () => { [298, 122, 12, 36, 98, 7, 24, 8, 125, 98, 125, 12, 36, 8]); }); +test('passes zoom level to reduce function', () => { + const zoomsReceived = new Set(); + const index = new Supercluster({ + map: props => ({sum: props.scalerank}), + reduce: (a, b, zoom) => { + a.sum += b.sum; + zoomsReceived.add(zoom); + }, + radius: 100, + minZoom: 0, + maxZoom: 5 + }).load(places.features); + + // Trigger clustering by getting clusters + index.getClusters([-180, -85, 180, 85], 0); + + // Verify zoom values were passed (should be integers from minZoom to maxZoom) + assert.ok(zoomsReceived.size > 0, 'reduce should have been called with zoom values'); + for (const zoom of zoomsReceived) { + assert.equal(typeof zoom, 'number', 'zoom should be a number'); + assert.ok(Number.isInteger(zoom), 'zoom should be an integer'); + assert.ok(zoom >= 0 && zoom <= 5, 'zoom should be within minZoom/maxZoom range'); + } +}); + test('returns clusters when query crosses international dateline', () => { const index = new Supercluster().load([ {