@flowmap.gl/layers 8.0.0-alpha.1 → 8.0.0-alpha.10

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.
@@ -19,51 +19,53 @@ import {ScatterplotLayer} from '@deck.gl/layers';
19
19
  import {
20
20
  colorAsRgba,
21
21
  FlowLinesLayerAttributes,
22
- FlowMapData,
23
- FlowMapDataAccessors,
24
- FlowMapDataProvider,
22
+ FlowmapData,
23
+ FlowmapDataAccessors,
24
+ FlowmapDataProvider,
25
25
  getFlowLineAttributesByIndex,
26
- getFlowMapColors,
26
+ getFlowmapColors,
27
27
  getOuterCircleRadiusByIndex,
28
- getLocationCentroidByIndex,
29
- isFlowMapData,
30
- isFlowMapDataProvider,
28
+ getLocationCoordsByIndex,
29
+ isFlowmapData,
30
+ isFlowmapDataProvider,
31
31
  LayersData,
32
- LocalFlowMapDataProvider,
32
+ LocalFlowmapDataProvider,
33
33
  LocationFilterMode,
34
34
  ViewportProps,
35
- FlowMapAggregateAccessors,
36
- ClusterNode,
37
- AggregateFlow,
35
+ FlowmapAggregateAccessors,
38
36
  } from '@flowmap.gl/data';
39
37
  import AnimatedFlowLinesLayer from './AnimatedFlowLinesLayer';
40
38
  import FlowCirclesLayer from './FlowCirclesLayer';
41
39
  import FlowLinesLayer from './FlowLinesLayer';
42
40
  import {
43
- FlowLayerPickingInfo,
41
+ FlowmapLayerPickingInfo,
44
42
  LayerProps,
45
43
  PickingInfo,
46
44
  PickingType,
47
45
  } from './types';
48
46
 
49
- export type FlowMapLayerProps<L, F> = {
50
- data: FlowMapData<L, F> | FlowMapDataProvider<L, F>;
47
+ export type FlowmapLayerProps<L, F> = {
48
+ data?: FlowmapData<L, F>;
49
+ dataProvider?: FlowmapDataProvider<L, F>;
51
50
  locationTotalsEnabled?: boolean;
52
51
  adaptiveScalesEnabled?: boolean;
53
52
  animationEnabled?: boolean;
54
53
  clusteringEnabled?: boolean;
55
54
  clusteringLevel?: number;
56
55
  fadeEnabled?: boolean;
56
+ fadeOpacityEnabled?: boolean;
57
57
  clusteringAuto?: boolean;
58
58
  darkMode?: boolean;
59
59
  fadeAmount?: number;
60
- colorScheme?: string;
60
+ colorScheme?: string | string[];
61
+ highlightColor?: string | number[];
62
+ maxTopFlowsDisplayNum?: number;
61
63
  onHover?: (
62
- info: FlowLayerPickingInfo<L, F> | undefined,
64
+ info: FlowmapLayerPickingInfo<L, F> | undefined,
63
65
  event: SourceEvent,
64
66
  ) => void;
65
- onClick?: (info: FlowLayerPickingInfo<L, F>, event: SourceEvent) => void;
66
- } & Partial<FlowMapDataAccessors<L, F>> &
67
+ onClick?: (info: FlowmapLayerPickingInfo<L, F>, event: SourceEvent) => void;
68
+ } & Partial<FlowmapDataAccessors<L, F>> &
67
69
  LayerProps;
68
70
 
69
71
  enum HighlightType {
@@ -73,7 +75,7 @@ enum HighlightType {
73
75
 
74
76
  type HighlightedLocationObject = {
75
77
  type: HighlightType.LOCATION;
76
- centroid: [number, number];
78
+ coords: [number, number];
77
79
  radius: number;
78
80
  };
79
81
 
@@ -85,15 +87,16 @@ type HighlightedFlowObject = {
85
87
  type HighlightedObject = HighlightedLocationObject | HighlightedFlowObject;
86
88
 
87
89
  type State<L, F> = {
88
- accessors: FlowMapAggregateAccessors<L, F>;
89
- dataProvider: FlowMapDataProvider<L, F>;
90
+ accessors: FlowmapAggregateAccessors<L, F>;
91
+ dataProvider: FlowmapDataProvider<L, F>;
90
92
  layersData: LayersData | undefined;
91
93
  highlightedObject: HighlightedObject | undefined;
94
+ pickingInfo: FlowmapLayerPickingInfo<L, F> | undefined;
92
95
  };
93
96
 
94
97
  export type SourceEvent = {srcEvent: MouseEvent};
95
98
 
96
- export default class FlowMapLayer<L, F> extends CompositeLayer {
99
+ export default class FlowmapLayer<L, F> extends CompositeLayer {
97
100
  static defaultProps = {
98
101
  darkMode: true,
99
102
  fadeAmount: 50,
@@ -101,16 +104,23 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
101
104
  animationEnabled: false,
102
105
  clusteringEnabled: true,
103
106
  fadeEnabled: true,
107
+ fadeOpacityEnabled: false,
104
108
  clusteringAuto: true,
105
109
  clusteringLevel: undefined,
106
110
  adaptiveScalesEnabled: true,
107
111
  colorScheme: 'Teal',
112
+ highlightColor: 'orange',
113
+ maxTopFlowsDisplayNum: 5000,
108
114
  };
109
115
  state: State<L, F> | undefined;
110
116
 
111
- public constructor(props: FlowMapLayerProps<L, F>) {
117
+ public constructor(props: FlowmapLayerProps<L, F>) {
112
118
  super({
113
119
  ...props,
120
+ dataProvider: {
121
+ // To avoid deck.gl props diffing on comlink worker proxy causing an exception
122
+ dataProvider: props.dataProvider,
123
+ },
114
124
  onHover: (info: PickingInfo<any>, event: SourceEvent) => {
115
125
  // TODO: if (lastHoverEventStartTimeRef > startTime) {
116
126
  // // Skipping, because this is not the latest hover event
@@ -119,15 +129,17 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
119
129
  this.setState({highlightedObject: this._getHighlightedObject(info)});
120
130
  const {onHover} = props;
121
131
  if (onHover) {
122
- this._getFlowLayerPickingInfo(info).then((info) =>
123
- onHover(info, event),
124
- );
132
+ this._getFlowmapLayerPickingInfo(info).then((info) => {
133
+ this.setState({pickingInfo: info});
134
+ onHover(info, event);
135
+ });
125
136
  }
126
137
  },
127
138
  onClick: (info: PickingInfo<any>, event: SourceEvent) => {
128
139
  const {onClick} = props;
129
140
  if (onClick) {
130
- this._getFlowLayerPickingInfo(info).then((info) => {
141
+ this._getFlowmapLayerPickingInfo(info).then((info) => {
142
+ this.setState({pickingInfo: info});
131
143
  if (info) {
132
144
  onClick(info, event);
133
145
  }
@@ -139,34 +151,43 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
139
151
 
140
152
  initializeState() {
141
153
  this.state = {
142
- accessors: new FlowMapAggregateAccessors<L, F>(this.props),
143
- dataProvider: this._makeDataProvider(),
154
+ accessors: new FlowmapAggregateAccessors<L, F>(this.props),
155
+ dataProvider: this._getOrMakeDataProvider(),
144
156
  layersData: undefined,
145
157
  highlightedObject: undefined,
158
+ pickingInfo: undefined,
159
+ };
160
+ }
161
+
162
+ getPickingInfo(pickParams: Record<string, any>) {
163
+ // This is for onHover event handlers set on the <DeckGL> component
164
+ return {
165
+ ...pickParams.info,
166
+ object: this.state?.pickingInfo?.object,
146
167
  };
147
168
  }
148
169
 
149
170
  private _updateAccessors() {
150
171
  this.state?.dataProvider?.setAccessors(this.props);
151
- this.setState({accessors: new FlowMapAggregateAccessors(this.props)});
172
+ this.setState({accessors: new FlowmapAggregateAccessors(this.props)});
152
173
  }
153
174
 
154
- private _makeDataProvider() {
155
- const {data} = this.props;
156
- if (isFlowMapDataProvider<L, F>(data)) {
157
- return data;
158
- } else if (isFlowMapData<L, F>(data)) {
159
- const dataProvider = new LocalFlowMapDataProvider<L, F>(this.props);
160
- dataProvider.setFlowMapData(data);
175
+ private _getOrMakeDataProvider() {
176
+ const {data, dataProvider} = this.props;
177
+ if (isFlowmapDataProvider<L, F>(dataProvider?.dataProvider)) {
178
+ return dataProvider.dataProvider;
179
+ } else if (isFlowmapData<L, F>(data)) {
180
+ const dataProvider = new LocalFlowmapDataProvider<L, F>(this.props);
181
+ dataProvider.setFlowmapData(data);
161
182
  return dataProvider;
162
183
  }
163
184
  throw new Error(
164
- 'FlowMapLayer: data must be a FlowMapDataProvider or FlowMapData',
185
+ 'FlowmapLayer: data must be a FlowmapDataProvider or FlowmapData',
165
186
  );
166
187
  }
167
188
 
168
189
  private _updateDataProvider() {
169
- this.setState({dataProvider: this._makeDataProvider()});
190
+ this.setState({dataProvider: this._getOrMakeDataProvider()});
170
191
  }
171
192
 
172
193
  shouldUpdateState(params: Record<string, any>): boolean {
@@ -189,7 +210,7 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
189
210
  }
190
211
 
191
212
  if (changeFlags.propsChanged) {
192
- this._updateAccessors();
213
+ // this._updateAccessors();
193
214
  }
194
215
  if (changeFlags.dataChanged) {
195
216
  this._updateDataProvider();
@@ -200,8 +221,11 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
200
221
  });
201
222
  }
202
223
 
203
- if (changeFlags.viewportChanged || changeFlags.propsOrDataChanged) {
204
- dataProvider.setFlowMapState(this._getFlowMapState());
224
+ if (
225
+ changeFlags.viewportChanged ||
226
+ changeFlags.propsOrDataChanged // TODO can we ignore accessor props changes?
227
+ ) {
228
+ dataProvider.setFlowmapState(this._getFlowmapState());
205
229
  (async () => {
206
230
  const layersData = await dataProvider.getLayersData();
207
231
  this.setState({layersData});
@@ -217,10 +241,13 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
217
241
  clusteringEnabled,
218
242
  clusteringLevel,
219
243
  fadeEnabled,
244
+ fadeOpacityEnabled,
220
245
  clusteringAuto,
221
246
  darkMode,
222
247
  fadeAmount,
223
248
  colorScheme,
249
+ highlightColor,
250
+ maxTopFlowsDisplayNum,
224
251
  } = this.props;
225
252
  return {
226
253
  locationTotalsEnabled,
@@ -229,16 +256,19 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
229
256
  clusteringEnabled,
230
257
  clusteringLevel,
231
258
  fadeEnabled,
259
+ fadeOpacityEnabled,
232
260
  clusteringAuto,
233
261
  darkMode,
234
262
  fadeAmount,
235
263
  colorScheme,
264
+ highlightColor,
265
+ maxTopFlowsDisplayNum,
236
266
  };
237
267
  }
238
268
 
239
- private _getFlowMapState() {
269
+ private _getFlowmapState() {
240
270
  return {
241
- viewport: asViewState(this.context.viewport),
271
+ viewport: pickViewportProps(this.context.viewport),
242
272
  filterState: {
243
273
  selectedLocations: undefined,
244
274
  locationFilterMode: LocationFilterMode.ALL,
@@ -248,9 +278,9 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
248
278
  };
249
279
  }
250
280
 
251
- private async _getFlowLayerPickingInfo(
281
+ private async _getFlowmapLayerPickingInfo(
252
282
  info: Record<string, any>,
253
- ): Promise<FlowLayerPickingInfo<L, F> | undefined> {
283
+ ): Promise<FlowmapLayerPickingInfo<L, F> | undefined> {
254
284
  const {index, sourceLayer} = info;
255
285
  const {dataProvider, accessors} = this.state || {};
256
286
  if (!dataProvider || !accessors) {
@@ -330,9 +360,25 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
330
360
  ) {
331
361
  const {lineAttributes} = this.state?.layersData || {};
332
362
  if (lineAttributes) {
363
+ let attrs = getFlowLineAttributesByIndex(lineAttributes, index);
364
+ if (this.props.fadeOpacityEnabled) {
365
+ attrs = {
366
+ ...attrs,
367
+ attributes: {
368
+ ...attrs.attributes,
369
+ getColor: {
370
+ ...attrs.attributes.getColor,
371
+ value: new Uint8Array([
372
+ ...attrs.attributes.getColor.value.slice(0, 3),
373
+ 255, // the highlight color should be always opaque
374
+ ]),
375
+ },
376
+ },
377
+ };
378
+ }
333
379
  return {
334
380
  type: HighlightType.FLOW,
335
- lineAttributes: getFlowLineAttributesByIndex(lineAttributes, index),
381
+ lineAttributes: attrs,
336
382
  };
337
383
  }
338
384
  } else if (sourceLayer instanceof FlowCirclesLayer) {
@@ -340,7 +386,7 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
340
386
  if (circleAttributes) {
341
387
  return {
342
388
  type: HighlightType.LOCATION,
343
- centroid: getLocationCentroidByIndex(circleAttributes, index),
389
+ coords: getLocationCoordsByIndex(circleAttributes, index),
344
390
  radius: getOuterCircleRadiusByIndex(circleAttributes, index),
345
391
  };
346
392
  }
@@ -354,9 +400,9 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
354
400
  const {layersData, highlightedObject} = this.state;
355
401
  const {circleAttributes, lineAttributes} = layersData || {};
356
402
  if (circleAttributes && lineAttributes) {
357
- const flowMapColors = getFlowMapColors(this._getSettingsState());
403
+ const flowmapColors = getFlowmapColors(this._getSettingsState());
358
404
  const outlineColor = colorAsRgba(
359
- flowMapColors.outlineColor || (this.props.darkMode ? '#000' : '#fff'),
405
+ flowmapColors.outlineColor || (this.props.darkMode ? '#000' : '#fff'),
360
406
  );
361
407
  const commonLineLayerProps = {
362
408
  data: lineAttributes,
@@ -395,8 +441,10 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
395
441
  this.getSubLayerProps({
396
442
  id: 'circles',
397
443
  data: circleAttributes,
398
- emptyColor: [0, 0, 0, 255],
399
- emptyOutlineColor: [0, 0, 0, 255],
444
+ emptyColor: this.props.darkMode
445
+ ? [0, 0, 0, 255]
446
+ : [255, 255, 255, 255],
447
+ outlineEmptyMix: 0.4,
400
448
  }),
401
449
  ),
402
450
  );
@@ -405,28 +453,34 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
405
453
  case HighlightType.LOCATION:
406
454
  layers.push(
407
455
  new ScatterplotLayer({
408
- id: 'location-highlight',
409
- data: [highlightedObject],
410
- stroked: true,
411
- filled: false,
412
- lineWidthUnits: 'pixels',
413
- getLineWidth: 2,
414
- radiusUnits: 'pixels',
415
- getRadius: (d: HighlightedLocationObject) => d.radius,
416
- getLineColor: (d: HighlightedLocationObject) =>
417
- colorAsRgba('orange'),
418
- getPosition: (d: HighlightedLocationObject) => d.centroid,
456
+ ...this.getSubLayerProps({
457
+ id: 'location-highlight',
458
+ data: [highlightedObject],
459
+ pickable: false,
460
+ antialiasing: true,
461
+ stroked: true,
462
+ filled: false,
463
+ lineWidthUnits: 'pixels',
464
+ getLineWidth: 2,
465
+ radiusUnits: 'pixels',
466
+ getRadius: (d: HighlightedLocationObject) => d.radius,
467
+ getLineColor: colorAsRgba(this.props.highlightColor),
468
+ getPosition: (d: HighlightedLocationObject) => d.coords,
469
+ }),
419
470
  }),
420
471
  );
421
472
  break;
422
473
  case HighlightType.FLOW:
423
474
  layers.push(
424
475
  new FlowLinesLayer({
425
- id: 'flow-highlight',
426
- data: highlightedObject.lineAttributes,
427
- drawOutline: true,
428
- outlineColor: colorAsRgba('orange'),
429
- outlineThickness: 1,
476
+ ...this.getSubLayerProps({
477
+ id: 'flow-highlight',
478
+ data: highlightedObject.lineAttributes,
479
+ drawOutline: true,
480
+ pickable: false,
481
+ outlineColor: colorAsRgba(this.props.highlightColor),
482
+ outlineThickness: 1,
483
+ }),
430
484
  }),
431
485
  );
432
486
  break;
@@ -439,7 +493,7 @@ export default class FlowMapLayer<L, F> extends CompositeLayer {
439
493
  }
440
494
  }
441
495
 
442
- function asViewState(viewport: Record<string, any>): ViewportProps {
496
+ function pickViewportProps(viewport: Record<string, any>): ViewportProps {
443
497
  const {width, height, longitude, latitude, zoom, pitch, bearing} = viewport;
444
498
  return {
445
499
  width,
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export {default as AnimatedFlowLinesLayer} from './AnimatedFlowLinesLayer';
2
2
  export {default as FlowLinesLayer} from './FlowLinesLayer';
3
3
  export {default as FlowCirclesLayer} from './FlowCirclesLayer';
4
- export {default as FlowMapLayer} from './FlowMapLayer';
5
- export type {FlowMapLayerProps} from './FlowMapLayer';
4
+ export {default as FlowmapLayer} from './FlowmapLayer';
5
+ export type {FlowmapLayerProps} from './FlowmapLayer';
6
6
 
7
7
  export * from './types';
package/src/types.ts CHANGED
@@ -45,7 +45,7 @@ export interface FlowPickingInfo<L, F> extends PickingInfo<F | AggregateFlow> {
45
45
  // object: FlowLocation;
46
46
  // }
47
47
 
48
- export type FlowLayerPickingInfo<L, F> =
48
+ export type FlowmapLayerPickingInfo<L, F> =
49
49
  | LocationPickingInfo<L>
50
50
  // | LocationAreaPickingInfo
51
51
  | FlowPickingInfo<L, F>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"FlowMapLayer.d.ts","sourceRoot":"","sources":["../src/FlowMapLayer.ts"],"names":[],"mappings":"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"}