@flowmap.gl/data 8.0.0-alpha.4 → 8.0.0-alpha.8
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/{FlowMapAggregateAccessors.d.ts → FlowmapAggregateAccessors.d.ts} +6 -6
- package/dist/{FlowMapAggregateAccessors.d.ts.map → FlowmapAggregateAccessors.d.ts.map} +1 -1
- package/dist/{FlowMapAggregateAccessors.js → FlowmapAggregateAccessors.js} +3 -3
- package/dist/{FlowMapSelectors.d.ts → FlowmapSelectors.d.ts} +47 -46
- package/dist/FlowmapSelectors.d.ts.map +1 -0
- package/dist/FlowmapSelectors.js +870 -0
- package/dist/{FlowMapState.d.ts → FlowmapState.d.ts} +5 -3
- package/dist/{FlowMapState.d.ts.map → FlowmapState.d.ts.map} +1 -1
- package/dist/{FlowMapState.js → FlowmapState.js} +1 -1
- package/dist/colors.d.ts +7 -7
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +20 -10
- package/dist/getViewStateForLocations.d.ts +18 -11
- package/dist/getViewStateForLocations.d.ts.map +1 -1
- package/dist/getViewStateForLocations.js +21 -18
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/provider/FlowmapDataProvider.d.ts +16 -0
- package/dist/provider/FlowmapDataProvider.d.ts.map +1 -0
- package/dist/provider/FlowmapDataProvider.js +17 -0
- package/dist/provider/LocalFlowmapDataProvider.d.ts +20 -0
- package/dist/provider/LocalFlowmapDataProvider.d.ts.map +1 -0
- package/dist/provider/LocalFlowmapDataProvider.js +95 -0
- package/dist/provider/WorkerFlowmapDataProvider.d.ts +42 -0
- package/dist/provider/WorkerFlowmapDataProvider.d.ts.map +1 -0
- package/dist/provider/WorkerFlowmapDataProvider.js +82 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.d.ts +2 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.d.ts.map +1 -0
- package/dist/provider/WorkerFlowmapDataProviderWorker.js +4 -0
- package/dist/provider/createWorkerDataProvider.d.ts +3 -0
- package/dist/provider/createWorkerDataProvider.d.ts.map +1 -0
- package/dist/provider/createWorkerDataProvider.js +21 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/package.json +7 -3
- package/src/{FlowMapAggregateAccessors.ts → FlowmapAggregateAccessors.ts} +6 -6
- package/src/{FlowMapSelectors.ts → FlowmapSelectors.ts} +89 -86
- package/src/{FlowMapState.ts → FlowmapState.ts} +4 -2
- package/src/colors.ts +22 -12
- package/src/getViewStateForLocations.ts +39 -35
- package/src/index.ts +9 -6
- package/src/provider/{FlowMapDataProvider.ts → FlowmapDataProvider.ts} +14 -12
- package/src/provider/LocalFlowmapDataProvider.ts +119 -0
- package/src/provider/WorkerFlowmapDataProvider.ts +121 -0
- package/src/provider/WorkerFlowmapDataProviderWorker.ts +4 -0
- package/src/provider/createWorkerDataProvider.ts +18 -0
- package/src/types.ts +2 -2
- package/dist/FlowMapSelectors.d.ts.map +0 -1
- package/dist/FlowMapSelectors.js +0 -869
- package/dist/provider/FlowMapDataProvider.d.ts +0 -16
- package/dist/provider/FlowMapDataProvider.d.ts.map +0 -1
- package/dist/provider/FlowMapDataProvider.js +0 -17
- package/dist/provider/LocalFlowMapDataProvider.d.ts +0 -20
- package/dist/provider/LocalFlowMapDataProvider.d.ts.map +0 -1
- package/dist/provider/LocalFlowMapDataProvider.js +0 -87
- package/src/provider/LocalFlowMapDataProvider.ts +0 -105
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import {WebMercatorViewport} from '@math.gl/web-mercator';
|
|
20
20
|
import {ascending, descending, extent, min} from 'd3-array';
|
|
21
21
|
import {nest} from 'd3-collection';
|
|
22
22
|
import {ScaleLinear, scaleLinear, scaleSqrt} from 'd3-scale';
|
|
@@ -44,8 +44,8 @@ import getColors, {
|
|
|
44
44
|
isDiffColors,
|
|
45
45
|
isDiffColorsRGBA,
|
|
46
46
|
} from './colors';
|
|
47
|
-
import
|
|
48
|
-
import {
|
|
47
|
+
import FlowmapAggregateAccessors from './FlowmapAggregateAccessors';
|
|
48
|
+
import {FlowmapState} from './FlowmapState';
|
|
49
49
|
import {
|
|
50
50
|
getTimeGranularityByKey,
|
|
51
51
|
getTimeGranularityByOrder,
|
|
@@ -60,8 +60,8 @@ import {
|
|
|
60
60
|
FlowAccessors,
|
|
61
61
|
FlowCirclesLayerAttributes,
|
|
62
62
|
FlowLinesLayerAttributes,
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
FlowmapData,
|
|
64
|
+
FlowmapDataAccessors,
|
|
65
65
|
isCluster,
|
|
66
66
|
isLocationClusterNode,
|
|
67
67
|
LayersData,
|
|
@@ -70,74 +70,75 @@ import {
|
|
|
70
70
|
} from './types';
|
|
71
71
|
|
|
72
72
|
const MAX_CLUSTER_ZOOM_LEVEL = 20;
|
|
73
|
-
const NUMBER_OF_FLOWS_TO_DISPLAY = 5000;
|
|
74
73
|
type KDBushTree = any;
|
|
75
74
|
|
|
76
75
|
export type Selector<L, F, T> = ParametricSelector<
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
FlowmapState,
|
|
77
|
+
FlowmapData<L, F>,
|
|
79
78
|
T
|
|
80
79
|
>;
|
|
81
80
|
|
|
82
|
-
export default class
|
|
83
|
-
accessors:
|
|
81
|
+
export default class FlowmapSelectors<L, F> {
|
|
82
|
+
accessors: FlowmapAggregateAccessors<L, F>;
|
|
84
83
|
|
|
85
|
-
constructor(accessors:
|
|
86
|
-
this.accessors = new
|
|
84
|
+
constructor(accessors: FlowmapDataAccessors<L, F>) {
|
|
85
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
87
86
|
this.setAccessors(accessors);
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
setAccessors(accessors:
|
|
91
|
-
this.accessors = new
|
|
89
|
+
setAccessors(accessors: FlowmapDataAccessors<L, F>) {
|
|
90
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
92
91
|
}
|
|
93
92
|
|
|
94
|
-
getFetchedFlows = (state:
|
|
93
|
+
getFetchedFlows = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
95
94
|
props.flows;
|
|
96
|
-
getFetchedLocations = (state:
|
|
95
|
+
getFetchedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
97
96
|
props.locations;
|
|
98
|
-
|
|
97
|
+
getMaxTopFlowsDisplayNum = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
98
|
+
state.settingsState.maxTopFlowsDisplayNum;
|
|
99
|
+
getSelectedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
99
100
|
state.filterState.selectedLocations;
|
|
100
|
-
getLocationFilterMode = (state:
|
|
101
|
+
getLocationFilterMode = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
101
102
|
state.filterState.locationFilterMode;
|
|
102
|
-
getClusteringEnabled = (state:
|
|
103
|
+
getClusteringEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
103
104
|
state.settingsState.clusteringEnabled;
|
|
104
|
-
getLocationTotalsEnabled = (state:
|
|
105
|
+
getLocationTotalsEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
105
106
|
state.settingsState.locationTotalsEnabled;
|
|
106
|
-
getZoom = (state:
|
|
107
|
+
getZoom = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
107
108
|
state.viewport.zoom;
|
|
108
|
-
getViewport = (state:
|
|
109
|
+
getViewport = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
109
110
|
state.viewport;
|
|
110
|
-
getSelectedTimeRange = (state:
|
|
111
|
+
getSelectedTimeRange = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
111
112
|
state.filterState.selectedTimeRange;
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
state:
|
|
115
|
-
props:
|
|
114
|
+
getColorScheme: Selector<L, F, string | string[] | undefined> = (
|
|
115
|
+
state: FlowmapState,
|
|
116
|
+
props: FlowmapData<L, F>,
|
|
116
117
|
) => state.settingsState.colorScheme;
|
|
117
118
|
|
|
118
119
|
getDarkMode: Selector<L, F, boolean> = (
|
|
119
|
-
state:
|
|
120
|
-
props:
|
|
120
|
+
state: FlowmapState,
|
|
121
|
+
props: FlowmapData<L, F>,
|
|
121
122
|
) => state.settingsState.darkMode;
|
|
122
123
|
|
|
123
124
|
getFadeEnabled: Selector<L, F, boolean> = (
|
|
124
|
-
state:
|
|
125
|
-
props:
|
|
125
|
+
state: FlowmapState,
|
|
126
|
+
props: FlowmapData<L, F>,
|
|
126
127
|
) => state.settingsState.fadeEnabled;
|
|
127
128
|
|
|
128
129
|
getFadeOpacityEnabled: Selector<L, F, boolean> = (
|
|
129
|
-
state:
|
|
130
|
-
props:
|
|
130
|
+
state: FlowmapState,
|
|
131
|
+
props: FlowmapData<L, F>,
|
|
131
132
|
) => state.settingsState.fadeOpacityEnabled;
|
|
132
133
|
|
|
133
134
|
getFadeAmount: Selector<L, F, number> = (
|
|
134
|
-
state:
|
|
135
|
-
props:
|
|
135
|
+
state: FlowmapState,
|
|
136
|
+
props: FlowmapData<L, F>,
|
|
136
137
|
) => state.settingsState.fadeAmount;
|
|
137
138
|
|
|
138
139
|
getAnimate: Selector<L, F, boolean> = (
|
|
139
|
-
state:
|
|
140
|
-
props:
|
|
140
|
+
state: FlowmapState,
|
|
141
|
+
props: FlowmapData<L, F>,
|
|
141
142
|
) => state.settingsState.animationEnabled;
|
|
142
143
|
|
|
143
144
|
getInvalidLocationIds: Selector<L, F, string[] | undefined> = createSelector(
|
|
@@ -308,11 +309,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
308
309
|
|
|
309
310
|
const getLocationWeight = makeLocationWeightGetter(
|
|
310
311
|
flows,
|
|
311
|
-
this.accessors.
|
|
312
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
312
313
|
);
|
|
313
314
|
const clusterLevels = clusterLocations(
|
|
314
315
|
locations,
|
|
315
|
-
this.accessors.
|
|
316
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
316
317
|
getLocationWeight,
|
|
317
318
|
{
|
|
318
319
|
maxZoom: MAX_CLUSTER_ZOOM_LEVEL,
|
|
@@ -320,7 +321,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
320
321
|
);
|
|
321
322
|
const clusterIndex = buildIndex<F>(clusterLevels);
|
|
322
323
|
const {getLocationName, getLocationClusterName} =
|
|
323
|
-
this.accessors.
|
|
324
|
+
this.accessors.getFlowmapDataAccessors();
|
|
324
325
|
|
|
325
326
|
// Adding meaningful names
|
|
326
327
|
const getName = (id: string) => {
|
|
@@ -415,7 +416,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
415
416
|
},
|
|
416
417
|
);
|
|
417
418
|
|
|
418
|
-
getClusterZoom = (state:
|
|
419
|
+
getClusterZoom = (state: FlowmapState, props: FlowmapData<L, F>) => {
|
|
419
420
|
const {settingsState} = state;
|
|
420
421
|
if (!settingsState.clusteringEnabled) return undefined;
|
|
421
422
|
if (settingsState.clusteringAuto || settingsState.clusteringLevel == null) {
|
|
@@ -486,9 +487,9 @@ export default class FlowMapSelectors<L, F> {
|
|
|
486
487
|
},
|
|
487
488
|
);
|
|
488
489
|
|
|
489
|
-
|
|
490
|
+
_getFlowmapColors = createSelector(
|
|
490
491
|
this.getDiffMode,
|
|
491
|
-
this.
|
|
492
|
+
this.getColorScheme,
|
|
492
493
|
this.getDarkMode,
|
|
493
494
|
this.getFadeEnabled,
|
|
494
495
|
this.getFadeOpacityEnabled,
|
|
@@ -497,12 +498,12 @@ export default class FlowMapSelectors<L, F> {
|
|
|
497
498
|
getColors,
|
|
498
499
|
);
|
|
499
500
|
|
|
500
|
-
|
|
501
|
-
this.
|
|
502
|
-
(
|
|
503
|
-
return isDiffColors(
|
|
504
|
-
? getDiffColorsRGBA(
|
|
505
|
-
: getColorsRGBA(
|
|
501
|
+
getFlowmapColorsRGBA = createSelector(
|
|
502
|
+
this._getFlowmapColors,
|
|
503
|
+
(flowmapColors) => {
|
|
504
|
+
return isDiffColors(flowmapColors)
|
|
505
|
+
? getDiffColorsRGBA(flowmapColors)
|
|
506
|
+
: getColorsRGBA(flowmapColors);
|
|
506
507
|
},
|
|
507
508
|
);
|
|
508
509
|
|
|
@@ -549,12 +550,12 @@ export default class FlowMapSelectors<L, F> {
|
|
|
549
550
|
// : flows,
|
|
550
551
|
flows,
|
|
551
552
|
clusterZoom,
|
|
552
|
-
this.accessors.
|
|
553
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
553
554
|
);
|
|
554
555
|
} else {
|
|
555
556
|
aggregated = aggregateFlows(
|
|
556
557
|
flows,
|
|
557
|
-
this.accessors.
|
|
558
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
558
559
|
);
|
|
559
560
|
}
|
|
560
561
|
aggregated.sort((a, b) =>
|
|
@@ -675,12 +676,12 @@ export default class FlowMapSelectors<L, F> {
|
|
|
675
676
|
this.getMaxLocationCircleSize,
|
|
676
677
|
(viewport, maxLocationCircleSize) => {
|
|
677
678
|
const pad = maxLocationCircleSize;
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
viewport.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
679
|
+
const bounds = new WebMercatorViewport({
|
|
680
|
+
...viewport,
|
|
681
|
+
width: viewport.width + pad * 2,
|
|
682
|
+
height: viewport.height + pad * 2,
|
|
683
|
+
}).getBounds();
|
|
684
|
+
return [bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]];
|
|
684
685
|
},
|
|
685
686
|
);
|
|
686
687
|
|
|
@@ -850,8 +851,8 @@ export default class FlowMapSelectors<L, F> {
|
|
|
850
851
|
);
|
|
851
852
|
|
|
852
853
|
getLocationTotalsExtent = (
|
|
853
|
-
state:
|
|
854
|
-
props:
|
|
854
|
+
state: FlowmapState,
|
|
855
|
+
props: FlowmapData<L, F>,
|
|
855
856
|
): [number, number] | undefined => {
|
|
856
857
|
if (state.settingsState.adaptiveScalesEnabled) {
|
|
857
858
|
return this._getLocationTotalsForViewportExtent(state, props);
|
|
@@ -860,17 +861,19 @@ export default class FlowMapSelectors<L, F> {
|
|
|
860
861
|
}
|
|
861
862
|
};
|
|
862
863
|
|
|
863
|
-
|
|
864
|
+
getFlowsForFlowmapLayer: Selector<L, F, (F | AggregateFlow)[] | undefined> =
|
|
864
865
|
createSelector(
|
|
865
866
|
this.getSortedAggregatedFilteredFlows,
|
|
866
867
|
this.getLocationIdsInViewport,
|
|
867
868
|
this.getSelectedLocationsSet,
|
|
868
869
|
this.getLocationFilterMode,
|
|
870
|
+
this.getMaxTopFlowsDisplayNum,
|
|
869
871
|
(
|
|
870
872
|
flows,
|
|
871
873
|
locationIdsInViewport,
|
|
872
874
|
selectedLocationsSet,
|
|
873
875
|
locationFilterMode,
|
|
876
|
+
maxTopFlowsDisplayNum,
|
|
874
877
|
) => {
|
|
875
878
|
if (!flows || !locationIdsInViewport) return undefined;
|
|
876
879
|
const picked: (F | AggregateFlow)[] = [];
|
|
@@ -897,7 +900,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
897
900
|
}
|
|
898
901
|
}
|
|
899
902
|
// Only keep top
|
|
900
|
-
if (pickedCount >
|
|
903
|
+
if (pickedCount > maxTopFlowsDisplayNum) break;
|
|
901
904
|
}
|
|
902
905
|
// assuming they are sorted in descending order,
|
|
903
906
|
// we need ascending for rendering
|
|
@@ -906,11 +909,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
906
909
|
);
|
|
907
910
|
|
|
908
911
|
_getFlowMagnitudeExtent = (
|
|
909
|
-
state:
|
|
910
|
-
props:
|
|
912
|
+
state: FlowmapState,
|
|
913
|
+
props: FlowmapData<L, F>,
|
|
911
914
|
): [number, number] | undefined => {
|
|
912
915
|
if (state.settingsState.adaptiveScalesEnabled) {
|
|
913
|
-
const flows = this.
|
|
916
|
+
const flows = this.getFlowsForFlowmapLayer(state, props);
|
|
914
917
|
if (flows) {
|
|
915
918
|
const rv = extent(flows, this.accessors.getFlowMagnitude);
|
|
916
919
|
return rv[0] !== undefined && rv[1] !== undefined ? rv : undefined;
|
|
@@ -1032,7 +1035,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1032
1035
|
},
|
|
1033
1036
|
);
|
|
1034
1037
|
|
|
1035
|
-
|
|
1038
|
+
getLocationsForFlowmapLayer: Selector<
|
|
1036
1039
|
L,
|
|
1037
1040
|
F,
|
|
1038
1041
|
Array<L | ClusterNode> | undefined
|
|
@@ -1062,11 +1065,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1062
1065
|
},
|
|
1063
1066
|
);
|
|
1064
1067
|
|
|
1065
|
-
|
|
1068
|
+
getLocationsForFlowmapLayerById: Selector<
|
|
1066
1069
|
L,
|
|
1067
1070
|
F,
|
|
1068
1071
|
Map<string, L | ClusterNode> | undefined
|
|
1069
|
-
> = createSelector(this.
|
|
1072
|
+
> = createSelector(this.getLocationsForFlowmapLayer, (locations) => {
|
|
1070
1073
|
if (!locations) return undefined;
|
|
1071
1074
|
return locations.reduce(
|
|
1072
1075
|
(m, d) => (m.set(this.accessors.getLocationId(d), d), m),
|
|
@@ -1075,10 +1078,10 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1075
1078
|
});
|
|
1076
1079
|
|
|
1077
1080
|
getLayersData: Selector<L, F, LayersData> = createSelector(
|
|
1078
|
-
this.
|
|
1079
|
-
this.
|
|
1080
|
-
this.
|
|
1081
|
-
this.
|
|
1081
|
+
this.getLocationsForFlowmapLayer,
|
|
1082
|
+
this.getFlowsForFlowmapLayer,
|
|
1083
|
+
this.getFlowmapColorsRGBA,
|
|
1084
|
+
this.getLocationsForFlowmapLayerById,
|
|
1082
1085
|
this.getLocationIdsInViewport,
|
|
1083
1086
|
this.getInCircleSizeGetter,
|
|
1084
1087
|
this.getOutCircleSizeGetter,
|
|
@@ -1087,7 +1090,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1087
1090
|
(
|
|
1088
1091
|
locations,
|
|
1089
1092
|
flows,
|
|
1090
|
-
|
|
1093
|
+
flowmapColors,
|
|
1091
1094
|
locationsById,
|
|
1092
1095
|
locationIdsInViewport,
|
|
1093
1096
|
getInCircleSize,
|
|
@@ -1098,7 +1101,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1098
1101
|
return this._prepareLayersData(
|
|
1099
1102
|
locations,
|
|
1100
1103
|
flows,
|
|
1101
|
-
|
|
1104
|
+
flowmapColors,
|
|
1102
1105
|
locationsById,
|
|
1103
1106
|
locationIdsInViewport,
|
|
1104
1107
|
getInCircleSize,
|
|
@@ -1109,11 +1112,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1109
1112
|
},
|
|
1110
1113
|
);
|
|
1111
1114
|
|
|
1112
|
-
prepareLayersData(state:
|
|
1113
|
-
const locations = this.
|
|
1114
|
-
const flows = this.
|
|
1115
|
-
const
|
|
1116
|
-
const locationsById = this.
|
|
1115
|
+
prepareLayersData(state: FlowmapState, props: FlowmapData<L, F>): LayersData {
|
|
1116
|
+
const locations = this.getLocationsForFlowmapLayer(state, props) || [];
|
|
1117
|
+
const flows = this.getFlowsForFlowmapLayer(state, props) || [];
|
|
1118
|
+
const flowmapColors = this.getFlowmapColorsRGBA(state, props);
|
|
1119
|
+
const locationsById = this.getLocationsForFlowmapLayerById(state, props);
|
|
1117
1120
|
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
1118
1121
|
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
1119
1122
|
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
@@ -1121,7 +1124,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1121
1124
|
return this._prepareLayersData(
|
|
1122
1125
|
locations,
|
|
1123
1126
|
flows,
|
|
1124
|
-
|
|
1127
|
+
flowmapColors,
|
|
1125
1128
|
locationsById,
|
|
1126
1129
|
locationIdsInViewport,
|
|
1127
1130
|
getInCircleSize,
|
|
@@ -1134,7 +1137,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1134
1137
|
_prepareLayersData(
|
|
1135
1138
|
locations: (L | ClusterNode)[] | undefined,
|
|
1136
1139
|
flows: (F | AggregateFlow)[] | undefined,
|
|
1137
|
-
|
|
1140
|
+
flowmapColors: DiffColorsRGBA | ColorsRGBA,
|
|
1138
1141
|
locationsById: Map<string, L | ClusterNode> | undefined,
|
|
1139
1142
|
locationIdsInViewport: Set<string> | undefined,
|
|
1140
1143
|
getInCircleSize: (locationId: string) => number,
|
|
@@ -1162,25 +1165,25 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1162
1165
|
number,
|
|
1163
1166
|
];
|
|
1164
1167
|
const flowColorScale = getFlowColorScale(
|
|
1165
|
-
|
|
1168
|
+
flowmapColors,
|
|
1166
1169
|
flowMagnitudeExtent,
|
|
1167
1170
|
false,
|
|
1168
1171
|
);
|
|
1169
1172
|
|
|
1170
|
-
// Using
|
|
1173
|
+
// Using a generator here helps to avoid creating intermediary arrays
|
|
1171
1174
|
const circlePositions = Float32Array.from(
|
|
1172
1175
|
(function* () {
|
|
1173
1176
|
for (const location of locations) {
|
|
1174
|
-
// yield* effectively
|
|
1177
|
+
// yield* effectively works as flatMap here
|
|
1175
1178
|
yield* getLocationCentroid(location);
|
|
1176
1179
|
}
|
|
1177
1180
|
})(),
|
|
1178
1181
|
);
|
|
1179
1182
|
|
|
1180
1183
|
// TODO: diff mode
|
|
1181
|
-
const circleColor = isDiffColorsRGBA(
|
|
1182
|
-
?
|
|
1183
|
-
:
|
|
1184
|
+
const circleColor = isDiffColorsRGBA(flowmapColors)
|
|
1185
|
+
? flowmapColors.positive.locationCircles.inner
|
|
1186
|
+
: flowmapColors.locationCircles.inner;
|
|
1184
1187
|
|
|
1185
1188
|
const circleColors = Uint8Array.from(
|
|
1186
1189
|
(function* () {
|
|
@@ -1251,7 +1254,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1251
1254
|
const staggeringValues = animationEnabled
|
|
1252
1255
|
? Float32Array.from(
|
|
1253
1256
|
(function* () {
|
|
1254
|
-
for (const
|
|
1257
|
+
for (const f of flows) {
|
|
1255
1258
|
// @ts-ignore
|
|
1256
1259
|
yield new alea(`${getFlowOriginId(f)}-${getFlowDestId(f)}`)();
|
|
1257
1260
|
}
|
|
@@ -17,10 +17,12 @@ export interface SettingsState {
|
|
|
17
17
|
clusteringLevel?: number;
|
|
18
18
|
darkMode: boolean;
|
|
19
19
|
fadeAmount: number;
|
|
20
|
-
colorScheme: string | undefined;
|
|
20
|
+
colorScheme: string | string[] | undefined;
|
|
21
|
+
highlightColor: string;
|
|
22
|
+
maxTopFlowsDisplayNum: number;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
export interface
|
|
25
|
+
export interface FlowmapState {
|
|
24
26
|
filterState: FilterState;
|
|
25
27
|
settingsState: SettingsState;
|
|
26
28
|
viewport: ViewportProps;
|
package/src/colors.ts
CHANGED
|
@@ -28,7 +28,7 @@ import {range} from 'd3-array';
|
|
|
28
28
|
import {scalePow, scaleSequential, scaleSequentialPow} from 'd3-scale';
|
|
29
29
|
import {interpolateBasis, interpolateRgbBasis} from 'd3-interpolate';
|
|
30
30
|
import {color as d3color, hcl, rgb as colorRgb} from 'd3-color';
|
|
31
|
-
import {SettingsState} from './
|
|
31
|
+
import {SettingsState} from './FlowmapState';
|
|
32
32
|
|
|
33
33
|
const DEFAULT_OUTLINE_COLOR = '#fff';
|
|
34
34
|
const DEFAULT_DIMMED_OPACITY = 0.4;
|
|
@@ -58,7 +58,10 @@ export function opacifyHex(hexCode: string, opacity: number): string {
|
|
|
58
58
|
return `rgba(${col.r}, ${col.g}, ${col.b}, ${opacity})`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export function colorAsRgba(color: string): RGBA {
|
|
61
|
+
export function colorAsRgba(color: string | number[]): RGBA {
|
|
62
|
+
if (Array.isArray(color)) {
|
|
63
|
+
return color as RGBA;
|
|
64
|
+
}
|
|
62
65
|
const col = d3color(color);
|
|
63
66
|
if (!col) {
|
|
64
67
|
console.warn('Invalid color: ', color);
|
|
@@ -100,7 +103,7 @@ const getColorSteps = (interpolate: (x: number) => string) =>
|
|
|
100
103
|
.reverse();
|
|
101
104
|
|
|
102
105
|
const FLOW_MIN_COLOR = 'rgba(240,240,240,0.5)';
|
|
103
|
-
export const
|
|
106
|
+
export const GRAYISH = [FLOW_MIN_COLOR, ColorScheme.primary];
|
|
104
107
|
const schemeBluYl = [
|
|
105
108
|
'#f7feae',
|
|
106
109
|
'#b7e6a5',
|
|
@@ -134,7 +137,6 @@ export const schemeTeal = [
|
|
|
134
137
|
export const DEFAULT_COLOR_SCHEME = schemeTeal;
|
|
135
138
|
export const COLOR_SCHEMES: {[key: string]: string[]} = {
|
|
136
139
|
Blues: asScheme(schemeBlues),
|
|
137
|
-
BluesPale: BLUES_PALE,
|
|
138
140
|
BluGrn: [
|
|
139
141
|
'#c4e6c3',
|
|
140
142
|
'#96d2a4',
|
|
@@ -186,6 +188,7 @@ export const COLOR_SCHEMES: {[key: string]: string[]} = {
|
|
|
186
188
|
],
|
|
187
189
|
Emrld: schemeEmrld,
|
|
188
190
|
GnBu: asScheme(schemeGnBu),
|
|
191
|
+
Grayish: GRAYISH,
|
|
189
192
|
Greens: asScheme(schemeGreens),
|
|
190
193
|
Greys: asScheme(schemeGreys),
|
|
191
194
|
Inferno: getColorSteps(interpolateInferno),
|
|
@@ -330,7 +333,7 @@ const diffColors: DiffColors = {
|
|
|
330
333
|
outlineColor: 'rgb(230,233,237)',
|
|
331
334
|
};
|
|
332
335
|
|
|
333
|
-
export function
|
|
336
|
+
export function getFlowmapColors(
|
|
334
337
|
settingsState: SettingsState,
|
|
335
338
|
): Colors | DiffColors {
|
|
336
339
|
return getColors(
|
|
@@ -346,7 +349,7 @@ export function getFlowMapColors(
|
|
|
346
349
|
|
|
347
350
|
export function getColors(
|
|
348
351
|
diffMode: boolean,
|
|
349
|
-
|
|
352
|
+
colorScheme: string | string[] | undefined,
|
|
350
353
|
darkMode: boolean,
|
|
351
354
|
fadeEnabled: boolean,
|
|
352
355
|
fadeOpacityEnabled: boolean,
|
|
@@ -357,11 +360,18 @@ export function getColors(
|
|
|
357
360
|
return diffColors;
|
|
358
361
|
}
|
|
359
362
|
|
|
360
|
-
let scheme
|
|
363
|
+
let scheme;
|
|
361
364
|
|
|
362
|
-
if (
|
|
363
|
-
scheme =
|
|
365
|
+
if (Array.isArray(colorScheme)) {
|
|
366
|
+
scheme = colorScheme;
|
|
367
|
+
} else {
|
|
368
|
+
scheme =
|
|
369
|
+
(colorScheme && COLOR_SCHEMES[colorScheme]) || DEFAULT_COLOR_SCHEME;
|
|
370
|
+
if (darkMode) {
|
|
371
|
+
scheme = scheme.slice().reverse();
|
|
372
|
+
}
|
|
364
373
|
}
|
|
374
|
+
|
|
365
375
|
// if (animate)
|
|
366
376
|
// if (fadeAmount > 0)
|
|
367
377
|
{
|
|
@@ -550,7 +560,7 @@ export interface LocationCircleColors {
|
|
|
550
560
|
incoming?: string;
|
|
551
561
|
highlighted?: string;
|
|
552
562
|
empty?: string;
|
|
553
|
-
|
|
563
|
+
outlineEmptyMix?: number;
|
|
554
564
|
}
|
|
555
565
|
|
|
556
566
|
export interface LocationAreaColors {
|
|
@@ -597,7 +607,7 @@ export interface LocationCircleColorsRGBA {
|
|
|
597
607
|
incoming: RGBA;
|
|
598
608
|
highlighted: RGBA;
|
|
599
609
|
empty: RGBA;
|
|
600
|
-
|
|
610
|
+
outlineEmptyMix: number;
|
|
601
611
|
}
|
|
602
612
|
|
|
603
613
|
export interface LocationAreaColorsRGBA {
|
|
@@ -682,7 +692,7 @@ function getFlowAndCircleColors(
|
|
|
682
692
|
flowColorHighlighted,
|
|
683
693
|
),
|
|
684
694
|
empty: emptyColor,
|
|
685
|
-
|
|
695
|
+
outlineEmptyMix: inputColors?.locationCircles?.outlineEmptyMix ?? 0.4,
|
|
686
696
|
},
|
|
687
697
|
};
|
|
688
698
|
}
|
|
@@ -1,41 +1,50 @@
|
|
|
1
|
-
import {BoundingBox, viewport} from '@mapbox/geo-viewport';
|
|
2
1
|
import {geoBounds} from 'd3-geo';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import {fitBounds} from '@math.gl/web-mercator';
|
|
3
|
+
import type {
|
|
4
|
+
FeatureCollection,
|
|
5
|
+
GeometryCollection,
|
|
6
|
+
GeometryObject,
|
|
7
|
+
} from 'geojson';
|
|
8
|
+
import type {ViewState} from './types';
|
|
5
9
|
|
|
6
10
|
export type LocationProperties = any;
|
|
7
11
|
|
|
12
|
+
export type GetViewStateOptions = {
|
|
13
|
+
pad?: number; // size ratio
|
|
14
|
+
padding?: {top: number; bottom: number; left: number; right: number};
|
|
15
|
+
tileSize?: number;
|
|
16
|
+
// minZoom?: number; // not supported by fitBounds
|
|
17
|
+
maxZoom?: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
8
20
|
export function getViewStateForFeatures(
|
|
9
21
|
featureCollection:
|
|
10
22
|
| FeatureCollection<GeometryObject, LocationProperties>
|
|
11
23
|
| GeometryCollection,
|
|
12
24
|
size: [number, number],
|
|
13
|
-
opts?:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
x2 + pad * (x2 - x1),
|
|
26
|
-
y2 + pad * (y2 - y1),
|
|
27
|
-
];
|
|
28
|
-
const {
|
|
29
|
-
center: [longitude, latitude],
|
|
30
|
-
zoom,
|
|
31
|
-
} = viewport(bounds, size, undefined, undefined, tileSize, true);
|
|
32
|
-
|
|
25
|
+
opts?: GetViewStateOptions,
|
|
26
|
+
): ViewState & {width: number; height: number} {
|
|
27
|
+
const {pad = 0.05, maxZoom = 100} = opts || {};
|
|
28
|
+
const bounds = geoBounds(featureCollection as any);
|
|
29
|
+
const [[x1, y1], [x2, y2]] = bounds;
|
|
30
|
+
const paddedBounds: [[number, number], [number, number]] = pad
|
|
31
|
+
? [
|
|
32
|
+
[x1 - pad * (x2 - x1), y1 - pad * (y2 - y1)],
|
|
33
|
+
[x2 + pad * (x2 - x1), y2 + pad * (y2 - y1)],
|
|
34
|
+
]
|
|
35
|
+
: bounds;
|
|
36
|
+
const [width, height] = size;
|
|
33
37
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
...fitBounds({
|
|
39
|
+
width,
|
|
40
|
+
height,
|
|
41
|
+
bounds: paddedBounds,
|
|
42
|
+
padding: opts?.padding,
|
|
43
|
+
// minZoom,
|
|
44
|
+
maxZoom,
|
|
45
|
+
}),
|
|
46
|
+
width,
|
|
47
|
+
height,
|
|
39
48
|
};
|
|
40
49
|
}
|
|
41
50
|
|
|
@@ -43,13 +52,8 @@ export function getViewStateForLocations(
|
|
|
43
52
|
locations: any[],
|
|
44
53
|
getLocationCentroid: (location: any) => [number, number],
|
|
45
54
|
size: [number, number],
|
|
46
|
-
opts?:
|
|
47
|
-
|
|
48
|
-
tileSize?: number;
|
|
49
|
-
minZoom?: number;
|
|
50
|
-
maxZoom?: number;
|
|
51
|
-
},
|
|
52
|
-
): ViewState {
|
|
55
|
+
opts?: GetViewStateOptions,
|
|
56
|
+
): ViewState & {width: number; height: number} {
|
|
53
57
|
return getViewStateForFeatures(
|
|
54
58
|
{
|
|
55
59
|
type: 'GeometryCollection',
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export * from './colors';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
3
|
+
export * from './FlowmapState';
|
|
4
|
+
export * from './FlowmapSelectors';
|
|
5
5
|
export * from './time';
|
|
6
6
|
export * from './getViewStateForLocations';
|
|
7
|
-
export * from './provider/
|
|
8
|
-
export {default as
|
|
9
|
-
export type {default as
|
|
10
|
-
export {default as
|
|
7
|
+
export * from './provider/FlowmapDataProvider';
|
|
8
|
+
export {default as FlowmapAggregateAccessors} from './FlowmapAggregateAccessors';
|
|
9
|
+
export type {default as FlowmapDataProvider} from './provider/FlowmapDataProvider';
|
|
10
|
+
export {default as LocalFlowmapDataProvider} from './provider/LocalFlowmapDataProvider';
|
|
11
|
+
export {default as createWorkerDataProvider} from './provider/createWorkerDataProvider';
|
|
12
|
+
export {default as WorkerFlowmapDataProvider} from './provider/WorkerFlowmapDataProvider';
|
|
13
|
+
export * from './provider/WorkerFlowmapDataProvider';
|