@deck.gl/carto 9.0.26 → 9.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cartoRasterTile-worker.js +1 -1
- package/dist/cartoSpatialTile-worker.js +1 -1
- package/dist/cartoVectorTile-worker.js +1 -1
- package/dist/dist.dev.js +68 -53
- package/dist/index.cjs +63 -53
- package/dist/index.cjs.map +3 -3
- package/dist/layers/cluster-tile-layer.d.ts.map +1 -1
- package/dist/layers/cluster-tile-layer.js +7 -6
- package/dist/layers/cluster-utils.d.ts +18 -6
- package/dist/layers/cluster-utils.d.ts.map +1 -1
- package/dist/layers/cluster-utils.js +19 -3
- package/dist/layers/schema/carto-raster-tile-loader.js +1 -1
- package/dist/layers/schema/carto-spatial-tile-loader.js +1 -1
- package/dist/layers/schema/carto-vector-tile-loader.js +1 -1
- package/dist/style/color-bins-style.js +2 -2
- package/dist/style/color-categories-style.js +2 -2
- package/dist/style/color-continuous-style.js +2 -2
- package/dist/style/utils.d.ts +2 -2
- package/dist/style/utils.d.ts.map +1 -1
- package/dist/style/utils.js +2 -2
- package/dist.min.js +8 -8
- package/package.json +2 -2
- package/src/layers/cluster-tile-layer.ts +13 -6
- package/src/layers/cluster-utils.ts +33 -6
- package/src/style/color-bins-style.ts +2 -2
- package/src/style/color-categories-style.ts +2 -2
- package/src/style/color-continuous-style.ts +2 -2
- package/src/style/utils.ts +6 -3
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "9.0.
|
|
6
|
+
"version": "9.0.28",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"@deck.gl/layers": "^9.0.0",
|
|
73
73
|
"@loaders.gl/core": "^4.2.0"
|
|
74
74
|
},
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "58a2526b9b910d3ce086d627643839c3cd8ee944"
|
|
76
76
|
}
|
|
@@ -122,26 +122,33 @@ class ClusterGeoJsonLayer<
|
|
|
122
122
|
|
|
123
123
|
const properties = extractAggregationProperties(visibleTiles[0]);
|
|
124
124
|
const data = [] as ClusteredFeaturePropertiesT<FeaturePropertiesT>[];
|
|
125
|
+
let needsUpdate = false;
|
|
125
126
|
for (const tile of visibleTiles) {
|
|
126
127
|
// Calculate aggregation based on viewport zoom
|
|
127
128
|
const overZoom = Math.round(zoom - tile.zoom);
|
|
128
129
|
const aggregationLevels = Math.round(clusterLevel) - overZoom;
|
|
129
|
-
|
|
130
|
+
const didAggregate = aggregateTile(
|
|
131
|
+
tile,
|
|
132
|
+
aggregationLevels,
|
|
133
|
+
properties,
|
|
134
|
+
getPosition,
|
|
135
|
+
getWeight
|
|
136
|
+
);
|
|
137
|
+
needsUpdate ||= didAggregate;
|
|
130
138
|
data.push(...tile.userData![aggregationLevels]);
|
|
131
139
|
}
|
|
132
140
|
|
|
133
141
|
data.sort((a, b) => Number(b.count - a.count));
|
|
134
142
|
|
|
135
143
|
const clusterIds = data?.map((tile: any) => tile.id);
|
|
136
|
-
|
|
144
|
+
needsUpdate ||= !deepEqual(clusterIds, this.state.clusterIds, 1);
|
|
137
145
|
this.setState({clusterIds});
|
|
138
146
|
|
|
139
147
|
if (needsUpdate) {
|
|
140
148
|
const stats = computeAggregationStats(data, properties);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
this.setState({data: clustersToBinary(data)});
|
|
149
|
+
const binaryData = clustersToBinary(data);
|
|
150
|
+
binaryData.points.attributes = {stats};
|
|
151
|
+
this.setState({data: binaryData});
|
|
145
152
|
}
|
|
146
153
|
|
|
147
154
|
const props = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {cellToParent} from 'quadbin';
|
|
2
2
|
import {_Tile2DHeader as Tile2DHeader} from '@deck.gl/geo-layers';
|
|
3
|
-
import {Accessor} from '@deck.gl/core';
|
|
3
|
+
import {Accessor, log} from '@deck.gl/core';
|
|
4
4
|
import {BinaryFeatureCollection} from '@loaders.gl/schema';
|
|
5
5
|
|
|
6
6
|
export type Aggregation = 'any' | 'average' | 'count' | 'min' | 'max' | 'sum';
|
|
@@ -12,23 +12,37 @@ export type ClusteredFeaturePropertiesT<FeaturePropertiesT> = FeaturePropertiesT
|
|
|
12
12
|
id: bigint;
|
|
13
13
|
count: number;
|
|
14
14
|
position: [number, number];
|
|
15
|
-
stats: Record<keyof FeaturePropertiesT, {min: number; max: number}>;
|
|
16
15
|
};
|
|
17
16
|
export type ParsedQuadbinCell<FeaturePropertiesT> = {id: bigint; properties: FeaturePropertiesT};
|
|
18
17
|
export type ParsedQuadbinTile<FeaturePropertiesT> = ParsedQuadbinCell<FeaturePropertiesT>[];
|
|
19
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Aggregates tile by specified properties, caching result in tile.userData
|
|
21
|
+
*
|
|
22
|
+
* @returns true if data was aggregated, false if cache used
|
|
23
|
+
*/
|
|
20
24
|
export function aggregateTile<FeaturePropertiesT>(
|
|
21
25
|
tile: Tile2DHeader<ParsedQuadbinTile<FeaturePropertiesT>>,
|
|
22
26
|
aggregationLevels: number,
|
|
23
27
|
properties: AggregationProperties<FeaturePropertiesT> = [],
|
|
24
28
|
getPosition: Accessor<ParsedQuadbinCell<FeaturePropertiesT>, [number, number]>,
|
|
25
29
|
getWeight: Accessor<ParsedQuadbinCell<FeaturePropertiesT>, number>
|
|
26
|
-
):
|
|
27
|
-
if (!tile.content) return;
|
|
30
|
+
): boolean {
|
|
31
|
+
if (!tile.content) return false;
|
|
28
32
|
|
|
29
33
|
// Aggregate on demand and cache result
|
|
30
34
|
if (!tile.userData) tile.userData = {};
|
|
31
|
-
|
|
35
|
+
const cell0 = tile.userData[aggregationLevels]?.[0];
|
|
36
|
+
if (cell0) {
|
|
37
|
+
// Have already aggregated this tile
|
|
38
|
+
if (properties.every(property => property.name in cell0)) {
|
|
39
|
+
// Use cached result
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Aggregated properties have changed, re-aggregate
|
|
44
|
+
tile.userData = {};
|
|
45
|
+
}
|
|
32
46
|
|
|
33
47
|
const out: Record<number, any> = {};
|
|
34
48
|
for (const cell of tile.content) {
|
|
@@ -80,6 +94,7 @@ export function aggregateTile<FeaturePropertiesT>(
|
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
tile.userData[aggregationLevels] = Object.values(out);
|
|
97
|
+
return true;
|
|
83
98
|
}
|
|
84
99
|
|
|
85
100
|
export function extractAggregationProperties<FeaturePropertiesT extends {}>(
|
|
@@ -90,6 +105,7 @@ export function extractAggregationProperties<FeaturePropertiesT extends {}>(
|
|
|
90
105
|
for (const name of Object.keys(tile.content![0].properties)) {
|
|
91
106
|
let aggregation = name.split('_').pop()!.toLowerCase() as Aggregation;
|
|
92
107
|
if (!validAggregations.includes(aggregation)) {
|
|
108
|
+
log.warn(`No valid aggregation present in ${name} property`)();
|
|
93
109
|
aggregation = 'any';
|
|
94
110
|
}
|
|
95
111
|
properties.push({name: name as keyof FeaturePropertiesT, aggregation});
|
|
@@ -125,9 +141,20 @@ const EMPTY_BINARY_PROPS = {
|
|
|
125
141
|
globalFeatureIds: {value: EMPTY_UINT16ARRAY, size: 1}
|
|
126
142
|
};
|
|
127
143
|
|
|
144
|
+
type BinaryFeatureCollectionWithStats<FeaturePropertiesT> = Omit<
|
|
145
|
+
BinaryFeatureCollection,
|
|
146
|
+
'points'
|
|
147
|
+
> & {
|
|
148
|
+
points: BinaryFeatureCollection['points'] & {
|
|
149
|
+
attributes?: {
|
|
150
|
+
stats: Record<keyof FeaturePropertiesT, {min: number; max: number}>;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
128
155
|
export function clustersToBinary<FeaturePropertiesT>(
|
|
129
156
|
data: ClusteredFeaturePropertiesT<FeaturePropertiesT>[]
|
|
130
|
-
):
|
|
157
|
+
): BinaryFeatureCollectionWithStats<FeaturePropertiesT> {
|
|
131
158
|
const positions = new Float32Array(data.length * 2);
|
|
132
159
|
const featureIds = new Uint16Array(data.length);
|
|
133
160
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -42,8 +42,8 @@ export default function colorBins<DataT = Feature>({
|
|
|
42
42
|
|
|
43
43
|
const color = scaleThreshold<number, Color>().domain(domain).range(palette);
|
|
44
44
|
|
|
45
|
-
return d => {
|
|
46
|
-
const value = getAttrValue(attr, d);
|
|
45
|
+
return (d, info) => {
|
|
46
|
+
const value = getAttrValue(attr, d, info);
|
|
47
47
|
return typeof value === 'number' && Number.isFinite(value) ? color(value) : nullColor;
|
|
48
48
|
};
|
|
49
49
|
}
|
|
@@ -48,8 +48,8 @@ export default function colorCategories<DataT = Feature>({
|
|
|
48
48
|
colorsByCategory[c] = palette[i];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
return d => {
|
|
52
|
-
const value = getAttrValue(attr, d);
|
|
51
|
+
return (d, info) => {
|
|
52
|
+
const value = getAttrValue(attr, d, info);
|
|
53
53
|
return (typeof value === 'number' && Number.isFinite(value)) || typeof value === 'string'
|
|
54
54
|
? colorsByCategory[value] || othersColor
|
|
55
55
|
: nullColor;
|
|
@@ -41,8 +41,8 @@ export default function colorContinuous<DataT = Feature>({
|
|
|
41
41
|
const palette = typeof colors === 'string' ? getPalette(colors, domain.length) : colors;
|
|
42
42
|
const color = scaleLinear<Color>().domain(domain).range(palette);
|
|
43
43
|
|
|
44
|
-
return d => {
|
|
45
|
-
const value = getAttrValue(attr, d);
|
|
44
|
+
return (d, info) => {
|
|
45
|
+
const value = getAttrValue(attr, d, info);
|
|
46
46
|
return typeof value === 'number' && Number.isFinite(value) ? color(value) : nullColor;
|
|
47
47
|
};
|
|
48
48
|
}
|
package/src/style/utils.ts
CHANGED
|
@@ -3,18 +3,21 @@ import {assert} from '../utils';
|
|
|
3
3
|
|
|
4
4
|
const ALLOWED_ATTR_TYPES = Object.freeze(['function', 'string']);
|
|
5
5
|
|
|
6
|
-
export type AttributeSelector<DataT = Feature, OutT = any> =
|
|
6
|
+
export type AttributeSelector<DataT = Feature, OutT = any> =
|
|
7
|
+
| string
|
|
8
|
+
| ((d: DataT, info: any) => OutT);
|
|
7
9
|
|
|
8
10
|
export function getAttrValue<DataT = Feature, OutT = any>(
|
|
9
11
|
attr: string | AttributeSelector<DataT, OutT>,
|
|
10
|
-
d: DataT
|
|
12
|
+
d: DataT,
|
|
13
|
+
info: any
|
|
11
14
|
): OutT {
|
|
12
15
|
assert(typeof d === 'object', 'Expected "data" to be an object');
|
|
13
16
|
assert(ALLOWED_ATTR_TYPES.includes(typeof attr), 'Expected "attr" to be a function or string');
|
|
14
17
|
|
|
15
18
|
// Is function
|
|
16
19
|
if (typeof attr === 'function') {
|
|
17
|
-
return attr(d);
|
|
20
|
+
return attr(d, info);
|
|
18
21
|
}
|
|
19
22
|
return (d as unknown as Feature)?.properties?.[attr] as OutT;
|
|
20
23
|
}
|