@deck.gl/carto 8.8.0-alpha.2 → 8.8.0-alpha.3

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.
Files changed (48) hide show
  1. package/dist/dist.dev.js +1479 -1085
  2. package/dist/es5/api/layer-map.js +17 -5
  3. package/dist/es5/api/layer-map.js.map +1 -1
  4. package/dist/es5/api/maps-api-common.js +1 -0
  5. package/dist/es5/api/maps-api-common.js.map +1 -1
  6. package/dist/es5/api/parseMap.js +14 -3
  7. package/dist/es5/api/parseMap.js.map +1 -1
  8. package/dist/es5/index.js +16 -0
  9. package/dist/es5/index.js.map +1 -1
  10. package/dist/es5/layers/carto-layer.js +13 -0
  11. package/dist/es5/layers/carto-layer.js.map +1 -1
  12. package/dist/es5/layers/h3-tile-layer.js +96 -0
  13. package/dist/es5/layers/h3-tile-layer.js.map +1 -0
  14. package/dist/es5/layers/h3-tileset-2d.js +165 -0
  15. package/dist/es5/layers/h3-tileset-2d.js.map +1 -0
  16. package/dist/es5/layers/quadkey-tile-layer.js +97 -0
  17. package/dist/es5/layers/quadkey-tile-layer.js.map +1 -0
  18. package/dist/es5/layers/quadkey-tileset-2d.js +89 -0
  19. package/dist/es5/layers/quadkey-tileset-2d.js.map +1 -0
  20. package/dist/esm/api/layer-map.js +12 -4
  21. package/dist/esm/api/layer-map.js.map +1 -1
  22. package/dist/esm/api/maps-api-common.js +1 -0
  23. package/dist/esm/api/maps-api-common.js.map +1 -1
  24. package/dist/esm/api/parseMap.js +15 -4
  25. package/dist/esm/api/parseMap.js.map +1 -1
  26. package/dist/esm/index.js +2 -0
  27. package/dist/esm/index.js.map +1 -1
  28. package/dist/esm/layers/carto-layer.js +12 -1
  29. package/dist/esm/layers/carto-layer.js.map +1 -1
  30. package/dist/esm/layers/h3-tile-layer.js +61 -0
  31. package/dist/esm/layers/h3-tile-layer.js.map +1 -0
  32. package/dist/esm/layers/h3-tileset-2d.js +103 -0
  33. package/dist/esm/layers/h3-tileset-2d.js.map +1 -0
  34. package/dist/esm/layers/quadkey-tile-layer.js +61 -0
  35. package/dist/esm/layers/quadkey-tile-layer.js.map +1 -0
  36. package/dist/esm/layers/quadkey-tileset-2d.js +48 -0
  37. package/dist/esm/layers/quadkey-tileset-2d.js.map +1 -0
  38. package/dist.min.js +14 -14
  39. package/package.json +2 -2
  40. package/src/api/layer-map.ts +14 -4
  41. package/src/api/maps-api-common.ts +1 -0
  42. package/src/api/parseMap.ts +20 -5
  43. package/src/index.ts +2 -0
  44. package/src/layers/carto-layer.ts +9 -1
  45. package/src/layers/h3-tile-layer.js +44 -0
  46. package/src/layers/h3-tileset-2d.js +82 -0
  47. package/src/layers/quadkey-tile-layer.js +42 -0
  48. package/src/layers/quadkey-tileset-2d.js +36 -0
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@deck.gl/carto",
3
3
  "description": "CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.",
4
4
  "license": "MIT",
5
- "version": "8.8.0-alpha.2",
5
+ "version": "8.8.0-alpha.3",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -58,5 +58,5 @@
58
58
  "@deck.gl/layers": "^8.0.0",
59
59
  "@loaders.gl/core": "^3.0.0"
60
60
  },
61
- "gitHead": "a52215449dff06fb683f5afd6399526353d11f35"
61
+ "gitHead": "edad7cf75b75a137d63ec89d2d644727d3082e25"
62
62
  }
@@ -42,6 +42,12 @@ export const AGGREGATION = {
42
42
  sum: 'SUM'
43
43
  };
44
44
 
45
+ export const OPACITY_MAP = {
46
+ getFillColor: 'opacity',
47
+ getLineColor: 'strokeOpacity',
48
+ getTextColor: 'opacity'
49
+ };
50
+
45
51
  const AGGREGATION_FUNC = {
46
52
  'count unique': (values, accessor) => groupSort(values, v => v.length, accessor).length,
47
53
  median,
@@ -71,7 +77,6 @@ const sharedPropMap = {
71
77
  enable3d: 'extruded',
72
78
  elevationScale: 'elevationScale',
73
79
  filled: 'filled',
74
- opacity: 'opacity',
75
80
  strokeColor: 'getLineColor',
76
81
  stroked: 'stroked',
77
82
  thickness: 'getLineWidth',
@@ -225,6 +230,10 @@ function normalizeAccessor(accessor, data) {
225
230
  return accessor;
226
231
  }
227
232
 
233
+ export function opacityToAlpha(opacity) {
234
+ return opacity !== undefined ? Math.round(255 * Math.pow(opacity, 1 / 2.2)) : 255;
235
+ }
236
+
228
237
  export function getColorValueAccessor({name}, colorAggregation, data: any) {
229
238
  const aggregator = AGGREGATION_FUNC[colorAggregation];
230
239
  const accessor = values => aggregator(values, p => p[name]);
@@ -259,11 +268,12 @@ export function getColorAccessor(
259
268
  scale.domain(domain);
260
269
  scale.range(scaleColor);
261
270
  scale.unknown(UNKNOWN_COLOR);
262
- const alpha = opacity !== undefined ? Math.round(255 * Math.pow(opacity, 1 / 2.2)) : 255;
271
+ const alpha = opacityToAlpha(opacity);
263
272
 
264
273
  const accessor = properties => {
265
- const {r, g, b} = rgb(scale(properties[name]));
266
- return [r, g, b, alpha];
274
+ const propertyValue = properties[name];
275
+ const {r, g, b} = rgb(scale(propertyValue));
276
+ return [r, g, b, propertyValue === null ? 0 : alpha];
267
277
  };
268
278
  return normalizeAccessor(accessor, data);
269
279
  }
@@ -35,6 +35,7 @@ export type Format = ValuesOf<typeof FORMATS>;
35
35
  // AVAILABLE FORMATS FOR TILES
36
36
  export const TILE_FORMATS = {
37
37
  MVT: 'mvt',
38
+ JSON: 'json',
38
39
  GEOJSON: 'geojson',
39
40
  BINARY: 'binary'
40
41
  } as const;
@@ -6,7 +6,9 @@ import {
6
6
  getColorValueAccessor,
7
7
  getSizeAccessor,
8
8
  getTextAccessor,
9
- getTextPixelOffsetAccessor
9
+ getTextPixelOffsetAccessor,
10
+ OPACITY_MAP,
11
+ opacityToAlpha
10
12
  } from './layer-map';
11
13
  import {_flatten as flatten, log} from '@deck.gl/core';
12
14
  import {assert} from '../utils';
@@ -131,10 +133,21 @@ function createStyleProps(config, mapping) {
131
133
  mapProps(config, result, mapping);
132
134
 
133
135
  // Kepler format sometimes omits strokeColor. TODO: remove once we can rely on
134
- // `strokeColor` always being sert when `stroke: true`.
136
+ // `strokeColor` always being set when `stroke: true`.
135
137
  if (result.stroked && !result.getLineColor) {
136
138
  result.getLineColor = result.getFillColor;
137
139
  }
140
+
141
+ for (const colorAccessor in OPACITY_MAP) {
142
+ if (Array.isArray(result[colorAccessor])) {
143
+ const color = [...result[colorAccessor]];
144
+ const opacityKey = OPACITY_MAP[colorAccessor];
145
+ const opacity = config.visConfig[opacityKey];
146
+ color[3] = opacityToAlpha(opacity);
147
+ result[colorAccessor] = color;
148
+ }
149
+ }
150
+
138
151
  result.highlightColor = config.visConfig.enable3d ? [255, 255, 255, 60] : [252, 242, 26, 255];
139
152
  return result;
140
153
  }
@@ -159,7 +172,7 @@ function createChannelProps(visualChannels, type, config, data) {
159
172
  if (!AGGREGATION[colorAggregation]) {
160
173
  result.getColorValue = getColorValueAccessor(colorField, colorAggregation, data);
161
174
  } else {
162
- result.getColorWeight = d => [colorField.name];
175
+ result.getColorWeight = d => d[colorField.name];
163
176
  }
164
177
  }
165
178
  } else if (colorField) {
@@ -167,13 +180,15 @@ function createChannelProps(visualChannels, type, config, data) {
167
180
  colorField,
168
181
  colorScale,
169
182
  visConfig.colorRange,
170
- 1, // Rely on layer opacity
183
+ visConfig.opacity,
171
184
  data
172
185
  );
173
186
  }
174
187
 
175
188
  if (strokeColorField) {
176
- const opacity = visConfig.strokeOpacity !== undefined ? visConfig.strokeOpacity : 1;
189
+ const fallbackOpacity = type === 'point' ? visConfig.opacity : 1;
190
+ const opacity =
191
+ visConfig.strokeOpacity !== undefined ? visConfig.strokeOpacity : fallbackOpacity;
177
192
  result.getLineColor = getColorAccessor(
178
193
  strokeColorField,
179
194
  strokeColorScale,
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export {getDefaultCredentials, setDefaultCredentials} from './config';
2
2
  export {default as CartoLayer} from './layers/carto-layer';
3
3
  export {default as _CartoTileLayer} from './layers/carto-tile-layer';
4
+ export {default as _H3TileLayer} from './layers/h3-tile-layer';
5
+ export {default as _QuadkeyTileLayer} from './layers/quadkey-tile-layer';
4
6
  export {default as BASEMAP} from './basemap';
5
7
  export {default as colorBins} from './style/color-bins-style';
6
8
  export {default as colorCategories} from './style/color-categories-style';
@@ -1,5 +1,7 @@
1
1
  import {CompositeLayer, Layer, log} from '@deck.gl/core';
2
2
  import CartoTileLayer from './carto-tile-layer';
3
+ import H3TileLayer from './h3-tile-layer';
4
+ import QuadkeyTileLayer from './quadkey-tile-layer';
3
5
  import {MVTLayer} from '@deck.gl/geo-layers';
4
6
  import {GeoJsonLayer} from '@deck.gl/layers';
5
7
  import {fetchLayerData, getDataV2, API_VERSIONS} from '../api';
@@ -240,7 +242,7 @@ export default class CartoLayer<DataT = any> extends CompositeLayer<CartoLayerPr
240
242
  source,
241
243
  clientId,
242
244
  credentials: credentials as CloudNativeCredentials,
243
- connection: connection as string,
245
+ connection,
244
246
  ...rest
245
247
  });
246
248
  }
@@ -283,6 +285,12 @@ export default class CartoLayer<DataT = any> extends CompositeLayer<CartoLayerPr
283
285
  (tileUrl.searchParams.get('formatTiles') as TileFormat) ||
284
286
  TILE_FORMATS.MVT;
285
287
 
288
+ if (data.scheme === 'h3') {
289
+ return [H3TileLayer, props];
290
+ }
291
+ if (data.scheme === 'quadkey') {
292
+ return [QuadkeyTileLayer, props];
293
+ }
286
294
  return props.formatTiles === TILE_FORMATS.MVT ? [MVTLayer, props] : [CartoTileLayer, props];
287
295
  }
288
296
 
@@ -0,0 +1,44 @@
1
+ import {CompositeLayer} from '@deck.gl/core';
2
+ import {H3HexagonLayer, TileLayer} from '@deck.gl/geo-layers';
3
+ import H3Tileset2D from './h3-tileset-2d';
4
+
5
+ const renderSubLayers = props => {
6
+ const {data} = props;
7
+ const {index} = props.tile;
8
+ if (!data || !data.length) return null;
9
+
10
+ return new H3HexagonLayer(props, {
11
+ centerHexagon: index,
12
+ highPrecision: true
13
+ });
14
+ };
15
+
16
+ export default class H3TileLayer extends CompositeLayer {
17
+ initializeState() {
18
+ this.setState({data: null, tileJSON: null});
19
+ }
20
+
21
+ updateState({props, oldProps, context, changeFlags}) {
22
+ if (changeFlags.dataChanged) {
23
+ let {data} = this.props;
24
+ const tileJSON = data;
25
+ data = tileJSON.tiles;
26
+ this.setState({data, tileJSON});
27
+ }
28
+ }
29
+
30
+ renderLayers() {
31
+ const {data} = this.state;
32
+ return [
33
+ new TileLayer(this.props, {
34
+ id: 'h3-tile-layer',
35
+ data,
36
+ getHexagon: d => d.id,
37
+ TilesetClass: H3Tileset2D,
38
+ renderSubLayers
39
+ })
40
+ ];
41
+ }
42
+ }
43
+
44
+ H3TileLayer.layerName = 'H3TileLayer';
@@ -0,0 +1,82 @@
1
+ import {_Tileset2D as Tileset2D} from '@deck.gl/geo-layers';
2
+ import {polyfill, getRes0Indexes, h3GetResolution, h3ToGeoBoundary, h3ToParent} from 'h3-js';
3
+
4
+ export function getHexagonsInBoundingBox({west, north, east, south}, resolution) {
5
+ if (resolution === 0) {
6
+ return getRes0Indexes();
7
+ }
8
+ if (east - west > 180) {
9
+ // This is a known issue in h3-js: polyfill does not work correctly
10
+ // when longitude span is larger than 180 degrees.
11
+ return getHexagonsInBoundingBox({west, north, east: 0, south}, resolution).concat(
12
+ getHexagonsInBoundingBox({west: 0, north, east, south}, resolution)
13
+ );
14
+ }
15
+
16
+ // `polyfill()` fills based on hexagon center, which means tiles vanish
17
+ // prematurely. Get more accurate coverage by oversampling
18
+ const oversample = 1;
19
+ const h3Indices = polyfill(
20
+ [
21
+ [
22
+ [west, north],
23
+ [west, south],
24
+ [east, south],
25
+ [east, north],
26
+ [west, north]
27
+ ]
28
+ ],
29
+ resolution + oversample,
30
+ true
31
+ );
32
+
33
+ return oversample ? [...new Set(h3Indices.map(i => h3ToParent(i, resolution)))] : h3Indices;
34
+ }
35
+
36
+ export function tileToBoundingBox(index) {
37
+ const coordinates = h3ToGeoBoundary(index);
38
+ const latitudes = coordinates.map(c => c[0]);
39
+ const longitudes = coordinates.map(c => c[1]);
40
+ const west = Math.min(...longitudes);
41
+ const south = Math.min(...latitudes);
42
+ const east = Math.max(...longitudes);
43
+ const north = Math.max(...latitudes);
44
+ return {west, south, east, north};
45
+ }
46
+
47
+ export default class H3Tileset2D extends Tileset2D {
48
+ getTileIndices({viewport, minZoom, maxZoom}) {
49
+ const [east, south, west, north] = viewport.getBounds();
50
+
51
+ // TODO ignores extent
52
+ let z = viewport.zoom;
53
+ if (typeof minZoom === 'number' && Number.isFinite(minZoom) && z < minZoom) {
54
+ z = minZoom;
55
+ }
56
+ if (typeof maxZoom === 'number' && Number.isFinite(maxZoom) && z > maxZoom) {
57
+ z = maxZoom;
58
+ }
59
+
60
+ // Heuristic to get h3 resolution
61
+ const resolution = Math.max(0, Math.floor((2 * z) / 3) - 2);
62
+ return getHexagonsInBoundingBox({west, north, east, south}, resolution).map(i => ({i}));
63
+ }
64
+
65
+ getTileId({i}) {
66
+ return i;
67
+ }
68
+
69
+ getTileMetadata({i}) {
70
+ return {bbox: tileToBoundingBox(i)};
71
+ }
72
+
73
+ getTileZoom({i}) {
74
+ return h3GetResolution(i);
75
+ }
76
+
77
+ getParentIndex(index) {
78
+ const resolution = h3GetResolution(index.i);
79
+ const i = h3ToParent(index.i, resolution - 1);
80
+ return {i};
81
+ }
82
+ }
@@ -0,0 +1,42 @@
1
+ import {CompositeLayer} from '@deck.gl/core';
2
+ import {QuadkeyLayer, TileLayer} from '@deck.gl/geo-layers';
3
+ import QuadkeyTileset2D from './quadkey-tileset-2d';
4
+
5
+ const renderSubLayers = props => {
6
+ const {data} = props;
7
+ if (!data || !data.length) return null;
8
+ return new QuadkeyLayer(props);
9
+ };
10
+
11
+ export default class QuadkeyTileLayer extends CompositeLayer {
12
+ initializeState() {
13
+ this.setState({data: null, tileJSON: null});
14
+ }
15
+
16
+ updateState({props, oldProps, context, changeFlags}) {
17
+ if (changeFlags.dataChanged) {
18
+ let {data} = this.props;
19
+ const tileJSON = data;
20
+ data = tileJSON.tiles;
21
+ this.setState({data, tileJSON});
22
+ }
23
+ }
24
+
25
+ renderLayers() {
26
+ const {data, tileJSON} = this.state;
27
+ const {maxresolution} = tileJSON;
28
+ const maxZoom = maxresolution - this.props.aggregationResLevel;
29
+ return [
30
+ new TileLayer(this.props, {
31
+ id: 'quadkey-tile-layer',
32
+ data,
33
+ getQuadkey: d => d.id,
34
+ TilesetClass: QuadkeyTileset2D,
35
+ renderSubLayers,
36
+ maxZoom
37
+ })
38
+ ];
39
+ }
40
+ }
41
+
42
+ QuadkeyTileLayer.layerName = 'QuadkeyTileLayer';
@@ -0,0 +1,36 @@
1
+ import {_Tileset2D as Tileset2D} from '@deck.gl/geo-layers';
2
+
3
+ function tileToQuadkey(tile) {
4
+ let index = '';
5
+ for (let z = tile.z; z > 0; z--) {
6
+ let b = 0;
7
+ const mask = 1 << (z - 1);
8
+ if ((tile.x & mask) !== 0) b++;
9
+ if ((tile.y & mask) !== 0) b += 2;
10
+ index += b.toString();
11
+ }
12
+ return {i: index};
13
+ }
14
+
15
+ export default class QuadkeyTileset2D extends Tileset2D {
16
+ getTileIndices(opts) {
17
+ return super.getTileIndices(opts).map(tileToQuadkey);
18
+ }
19
+
20
+ getTileId({i}) {
21
+ return i;
22
+ }
23
+
24
+ getTileMetadata() {
25
+ return {};
26
+ }
27
+
28
+ getTileZoom({i}) {
29
+ return i.length;
30
+ }
31
+
32
+ getParentIndex(index) {
33
+ const i = index.i.slice(0, -1);
34
+ return {i};
35
+ }
36
+ }