@flowmap.gl/data 8.0.0-alpha.2 → 8.0.0-alpha.6
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 -45
- package/dist/FlowmapSelectors.d.ts.map +1 -0
- package/dist/FlowmapSelectors.js +869 -0
- package/dist/{FlowMapState.d.ts → FlowmapState.d.ts} +5 -2
- package/dist/FlowmapState.d.ts.map +1 -0
- package/dist/FlowmapState.js +2 -0
- package/dist/colors.d.ts +6 -6
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +42 -17
- package/dist/getViewStateForLocations.d.ts +12 -10
- package/dist/getViewStateForLocations.d.ts.map +1 -1
- package/dist/getViewStateForLocations.js +4 -1
- 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/dist/util.d.ts +0 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +1 -4
- package/package.json +7 -2
- package/src/{FlowMapAggregateAccessors.ts → FlowmapAggregateAccessors.ts} +6 -6
- package/src/{FlowMapSelectors.ts → FlowmapSelectors.ts} +154 -113
- package/src/{FlowMapState.ts → FlowmapState.ts} +4 -1
- package/src/colors.ts +50 -16
- package/src/getViewStateForLocations.ts +20 -16
- 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/src/util.ts +0 -4
- package/dist/FlowMapSelectors.d.ts.map +0 -1
- package/dist/FlowMapSelectors.js +0 -834
- package/dist/FlowMapState.d.ts.map +0 -1
- package/dist/FlowMapState.js +0 -2
- 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
|
@@ -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,80 +60,85 @@ 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,
|
|
68
68
|
LocationFilterMode,
|
|
69
69
|
LocationTotals,
|
|
70
70
|
} from './types';
|
|
71
|
-
import {flatMap} from './util';
|
|
72
71
|
|
|
73
72
|
const MAX_CLUSTER_ZOOM_LEVEL = 20;
|
|
74
|
-
const NUMBER_OF_FLOWS_TO_DISPLAY = 5000;
|
|
75
73
|
type KDBushTree = any;
|
|
76
74
|
|
|
77
75
|
export type Selector<L, F, T> = ParametricSelector<
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
FlowmapState,
|
|
77
|
+
FlowmapData<L, F>,
|
|
80
78
|
T
|
|
81
79
|
>;
|
|
82
80
|
|
|
83
|
-
export default class
|
|
84
|
-
accessors:
|
|
81
|
+
export default class FlowmapSelectors<L, F> {
|
|
82
|
+
accessors: FlowmapAggregateAccessors<L, F>;
|
|
85
83
|
|
|
86
|
-
constructor(accessors:
|
|
87
|
-
this.accessors = new
|
|
84
|
+
constructor(accessors: FlowmapDataAccessors<L, F>) {
|
|
85
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
88
86
|
this.setAccessors(accessors);
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
setAccessors(accessors:
|
|
92
|
-
this.accessors = new
|
|
89
|
+
setAccessors(accessors: FlowmapDataAccessors<L, F>) {
|
|
90
|
+
this.accessors = new FlowmapAggregateAccessors(accessors);
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
getFetchedFlows = (state:
|
|
93
|
+
getFetchedFlows = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
96
94
|
props.flows;
|
|
97
|
-
getFetchedLocations = (state:
|
|
95
|
+
getFetchedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
98
96
|
props.locations;
|
|
99
|
-
|
|
97
|
+
getMaxTopFlowsDisplayNum = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
98
|
+
state.settingsState.maxTopFlowsDisplayNum;
|
|
99
|
+
getSelectedLocations = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
100
100
|
state.filterState.selectedLocations;
|
|
101
|
-
getLocationFilterMode = (state:
|
|
101
|
+
getLocationFilterMode = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
102
102
|
state.filterState.locationFilterMode;
|
|
103
|
-
getClusteringEnabled = (state:
|
|
103
|
+
getClusteringEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
104
104
|
state.settingsState.clusteringEnabled;
|
|
105
|
-
getLocationTotalsEnabled = (state:
|
|
105
|
+
getLocationTotalsEnabled = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
106
106
|
state.settingsState.locationTotalsEnabled;
|
|
107
|
-
getZoom = (state:
|
|
107
|
+
getZoom = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
108
108
|
state.viewport.zoom;
|
|
109
|
-
getViewport = (state:
|
|
109
|
+
getViewport = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
110
110
|
state.viewport;
|
|
111
|
-
getSelectedTimeRange = (state:
|
|
111
|
+
getSelectedTimeRange = (state: FlowmapState, props: FlowmapData<L, F>) =>
|
|
112
112
|
state.filterState.selectedTimeRange;
|
|
113
113
|
|
|
114
114
|
getColorSchemeKey: Selector<L, F, string | undefined> = (
|
|
115
|
-
state:
|
|
116
|
-
props:
|
|
115
|
+
state: FlowmapState,
|
|
116
|
+
props: FlowmapData<L, F>,
|
|
117
117
|
) => state.settingsState.colorScheme;
|
|
118
118
|
|
|
119
119
|
getDarkMode: Selector<L, F, boolean> = (
|
|
120
|
-
state:
|
|
121
|
-
props:
|
|
120
|
+
state: FlowmapState,
|
|
121
|
+
props: FlowmapData<L, F>,
|
|
122
122
|
) => state.settingsState.darkMode;
|
|
123
123
|
|
|
124
124
|
getFadeEnabled: Selector<L, F, boolean> = (
|
|
125
|
-
state:
|
|
126
|
-
props:
|
|
125
|
+
state: FlowmapState,
|
|
126
|
+
props: FlowmapData<L, F>,
|
|
127
127
|
) => state.settingsState.fadeEnabled;
|
|
128
128
|
|
|
129
|
+
getFadeOpacityEnabled: Selector<L, F, boolean> = (
|
|
130
|
+
state: FlowmapState,
|
|
131
|
+
props: FlowmapData<L, F>,
|
|
132
|
+
) => state.settingsState.fadeOpacityEnabled;
|
|
133
|
+
|
|
129
134
|
getFadeAmount: Selector<L, F, number> = (
|
|
130
|
-
state:
|
|
131
|
-
props:
|
|
135
|
+
state: FlowmapState,
|
|
136
|
+
props: FlowmapData<L, F>,
|
|
132
137
|
) => state.settingsState.fadeAmount;
|
|
133
138
|
|
|
134
139
|
getAnimate: Selector<L, F, boolean> = (
|
|
135
|
-
state:
|
|
136
|
-
props:
|
|
140
|
+
state: FlowmapState,
|
|
141
|
+
props: FlowmapData<L, F>,
|
|
137
142
|
) => state.settingsState.animationEnabled;
|
|
138
143
|
|
|
139
144
|
getInvalidLocationIds: Selector<L, F, string[] | undefined> = createSelector(
|
|
@@ -304,11 +309,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
304
309
|
|
|
305
310
|
const getLocationWeight = makeLocationWeightGetter(
|
|
306
311
|
flows,
|
|
307
|
-
this.accessors.
|
|
312
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
308
313
|
);
|
|
309
314
|
const clusterLevels = clusterLocations(
|
|
310
315
|
locations,
|
|
311
|
-
this.accessors.
|
|
316
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
312
317
|
getLocationWeight,
|
|
313
318
|
{
|
|
314
319
|
maxZoom: MAX_CLUSTER_ZOOM_LEVEL,
|
|
@@ -316,7 +321,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
316
321
|
);
|
|
317
322
|
const clusterIndex = buildIndex<F>(clusterLevels);
|
|
318
323
|
const {getLocationName, getLocationClusterName} =
|
|
319
|
-
this.accessors.
|
|
324
|
+
this.accessors.getFlowmapDataAccessors();
|
|
320
325
|
|
|
321
326
|
// Adding meaningful names
|
|
322
327
|
const getName = (id: string) => {
|
|
@@ -411,7 +416,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
411
416
|
},
|
|
412
417
|
);
|
|
413
418
|
|
|
414
|
-
getClusterZoom = (state:
|
|
419
|
+
getClusterZoom = (state: FlowmapState, props: FlowmapData<L, F>) => {
|
|
415
420
|
const {settingsState} = state;
|
|
416
421
|
if (!settingsState.clusteringEnabled) return undefined;
|
|
417
422
|
if (settingsState.clusteringAuto || settingsState.clusteringLevel == null) {
|
|
@@ -482,22 +487,23 @@ export default class FlowMapSelectors<L, F> {
|
|
|
482
487
|
},
|
|
483
488
|
);
|
|
484
489
|
|
|
485
|
-
|
|
490
|
+
_getFlowmapColors = createSelector(
|
|
486
491
|
this.getDiffMode,
|
|
487
492
|
this.getColorSchemeKey,
|
|
488
493
|
this.getDarkMode,
|
|
489
494
|
this.getFadeEnabled,
|
|
495
|
+
this.getFadeOpacityEnabled,
|
|
490
496
|
this.getFadeAmount,
|
|
491
497
|
this.getAnimate,
|
|
492
498
|
getColors,
|
|
493
499
|
);
|
|
494
500
|
|
|
495
|
-
|
|
496
|
-
this.
|
|
497
|
-
(
|
|
498
|
-
return isDiffColors(
|
|
499
|
-
? getDiffColorsRGBA(
|
|
500
|
-
: getColorsRGBA(
|
|
501
|
+
getFlowmapColorsRGBA = createSelector(
|
|
502
|
+
this._getFlowmapColors,
|
|
503
|
+
(flowmapColors) => {
|
|
504
|
+
return isDiffColors(flowmapColors)
|
|
505
|
+
? getDiffColorsRGBA(flowmapColors)
|
|
506
|
+
: getColorsRGBA(flowmapColors);
|
|
501
507
|
},
|
|
502
508
|
);
|
|
503
509
|
|
|
@@ -544,12 +550,12 @@ export default class FlowMapSelectors<L, F> {
|
|
|
544
550
|
// : flows,
|
|
545
551
|
flows,
|
|
546
552
|
clusterZoom,
|
|
547
|
-
this.accessors.
|
|
553
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
548
554
|
);
|
|
549
555
|
} else {
|
|
550
556
|
aggregated = aggregateFlows(
|
|
551
557
|
flows,
|
|
552
|
-
this.accessors.
|
|
558
|
+
this.accessors.getFlowmapDataAccessors(),
|
|
553
559
|
);
|
|
554
560
|
}
|
|
555
561
|
aggregated.sort((a, b) =>
|
|
@@ -845,8 +851,8 @@ export default class FlowMapSelectors<L, F> {
|
|
|
845
851
|
);
|
|
846
852
|
|
|
847
853
|
getLocationTotalsExtent = (
|
|
848
|
-
state:
|
|
849
|
-
props:
|
|
854
|
+
state: FlowmapState,
|
|
855
|
+
props: FlowmapData<L, F>,
|
|
850
856
|
): [number, number] | undefined => {
|
|
851
857
|
if (state.settingsState.adaptiveScalesEnabled) {
|
|
852
858
|
return this._getLocationTotalsForViewportExtent(state, props);
|
|
@@ -855,17 +861,19 @@ export default class FlowMapSelectors<L, F> {
|
|
|
855
861
|
}
|
|
856
862
|
};
|
|
857
863
|
|
|
858
|
-
|
|
864
|
+
getFlowsForFlowmapLayer: Selector<L, F, (F | AggregateFlow)[] | undefined> =
|
|
859
865
|
createSelector(
|
|
860
866
|
this.getSortedAggregatedFilteredFlows,
|
|
861
867
|
this.getLocationIdsInViewport,
|
|
862
868
|
this.getSelectedLocationsSet,
|
|
863
869
|
this.getLocationFilterMode,
|
|
870
|
+
this.getMaxTopFlowsDisplayNum,
|
|
864
871
|
(
|
|
865
872
|
flows,
|
|
866
873
|
locationIdsInViewport,
|
|
867
874
|
selectedLocationsSet,
|
|
868
875
|
locationFilterMode,
|
|
876
|
+
maxTopFlowsDisplayNum,
|
|
869
877
|
) => {
|
|
870
878
|
if (!flows || !locationIdsInViewport) return undefined;
|
|
871
879
|
const picked: (F | AggregateFlow)[] = [];
|
|
@@ -892,7 +900,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
892
900
|
}
|
|
893
901
|
}
|
|
894
902
|
// Only keep top
|
|
895
|
-
if (pickedCount >
|
|
903
|
+
if (pickedCount > maxTopFlowsDisplayNum) break;
|
|
896
904
|
}
|
|
897
905
|
// assuming they are sorted in descending order,
|
|
898
906
|
// we need ascending for rendering
|
|
@@ -901,11 +909,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
901
909
|
);
|
|
902
910
|
|
|
903
911
|
_getFlowMagnitudeExtent = (
|
|
904
|
-
state:
|
|
905
|
-
props:
|
|
912
|
+
state: FlowmapState,
|
|
913
|
+
props: FlowmapData<L, F>,
|
|
906
914
|
): [number, number] | undefined => {
|
|
907
915
|
if (state.settingsState.adaptiveScalesEnabled) {
|
|
908
|
-
const flows = this.
|
|
916
|
+
const flows = this.getFlowsForFlowmapLayer(state, props);
|
|
909
917
|
if (flows) {
|
|
910
918
|
const rv = extent(flows, this.accessors.getFlowMagnitude);
|
|
911
919
|
return rv[0] !== undefined && rv[1] !== undefined ? rv : undefined;
|
|
@@ -1027,7 +1035,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1027
1035
|
},
|
|
1028
1036
|
);
|
|
1029
1037
|
|
|
1030
|
-
|
|
1038
|
+
getLocationsForFlowmapLayer: Selector<
|
|
1031
1039
|
L,
|
|
1032
1040
|
F,
|
|
1033
1041
|
Array<L | ClusterNode> | undefined
|
|
@@ -1057,11 +1065,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1057
1065
|
},
|
|
1058
1066
|
);
|
|
1059
1067
|
|
|
1060
|
-
|
|
1068
|
+
getLocationsForFlowmapLayerById: Selector<
|
|
1061
1069
|
L,
|
|
1062
1070
|
F,
|
|
1063
1071
|
Map<string, L | ClusterNode> | undefined
|
|
1064
|
-
> = createSelector(this.
|
|
1072
|
+
> = createSelector(this.getLocationsForFlowmapLayer, (locations) => {
|
|
1065
1073
|
if (!locations) return undefined;
|
|
1066
1074
|
return locations.reduce(
|
|
1067
1075
|
(m, d) => (m.set(this.accessors.getLocationId(d), d), m),
|
|
@@ -1070,10 +1078,10 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1070
1078
|
});
|
|
1071
1079
|
|
|
1072
1080
|
getLayersData: Selector<L, F, LayersData> = createSelector(
|
|
1073
|
-
this.
|
|
1074
|
-
this.
|
|
1075
|
-
this.
|
|
1076
|
-
this.
|
|
1081
|
+
this.getLocationsForFlowmapLayer,
|
|
1082
|
+
this.getFlowsForFlowmapLayer,
|
|
1083
|
+
this.getFlowmapColorsRGBA,
|
|
1084
|
+
this.getLocationsForFlowmapLayerById,
|
|
1077
1085
|
this.getLocationIdsInViewport,
|
|
1078
1086
|
this.getInCircleSizeGetter,
|
|
1079
1087
|
this.getOutCircleSizeGetter,
|
|
@@ -1082,7 +1090,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1082
1090
|
(
|
|
1083
1091
|
locations,
|
|
1084
1092
|
flows,
|
|
1085
|
-
|
|
1093
|
+
flowmapColors,
|
|
1086
1094
|
locationsById,
|
|
1087
1095
|
locationIdsInViewport,
|
|
1088
1096
|
getInCircleSize,
|
|
@@ -1093,7 +1101,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1093
1101
|
return this._prepareLayersData(
|
|
1094
1102
|
locations,
|
|
1095
1103
|
flows,
|
|
1096
|
-
|
|
1104
|
+
flowmapColors,
|
|
1097
1105
|
locationsById,
|
|
1098
1106
|
locationIdsInViewport,
|
|
1099
1107
|
getInCircleSize,
|
|
@@ -1104,11 +1112,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1104
1112
|
},
|
|
1105
1113
|
);
|
|
1106
1114
|
|
|
1107
|
-
prepareLayersData(state:
|
|
1108
|
-
const locations = this.
|
|
1109
|
-
const flows = this.
|
|
1110
|
-
const
|
|
1111
|
-
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);
|
|
1112
1120
|
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
1113
1121
|
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
1114
1122
|
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
@@ -1116,7 +1124,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1116
1124
|
return this._prepareLayersData(
|
|
1117
1125
|
locations,
|
|
1118
1126
|
flows,
|
|
1119
|
-
|
|
1127
|
+
flowmapColors,
|
|
1120
1128
|
locationsById,
|
|
1121
1129
|
locationIdsInViewport,
|
|
1122
1130
|
getInCircleSize,
|
|
@@ -1129,7 +1137,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1129
1137
|
_prepareLayersData(
|
|
1130
1138
|
locations: (L | ClusterNode)[] | undefined,
|
|
1131
1139
|
flows: (F | AggregateFlow)[] | undefined,
|
|
1132
|
-
|
|
1140
|
+
flowmapColors: DiffColorsRGBA | ColorsRGBA,
|
|
1133
1141
|
locationsById: Map<string, L | ClusterNode> | undefined,
|
|
1134
1142
|
locationIdsInViewport: Set<string> | undefined,
|
|
1135
1143
|
getInCircleSize: (locationId: string) => number,
|
|
@@ -1157,67 +1165,100 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1157
1165
|
number,
|
|
1158
1166
|
];
|
|
1159
1167
|
const flowColorScale = getFlowColorScale(
|
|
1160
|
-
|
|
1168
|
+
flowmapColors,
|
|
1161
1169
|
flowMagnitudeExtent,
|
|
1162
1170
|
false,
|
|
1163
1171
|
);
|
|
1164
1172
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1173
|
+
// Using a generator here helps to avoid creating intermediary arrays
|
|
1174
|
+
const circlePositions = Float32Array.from(
|
|
1175
|
+
(function* () {
|
|
1176
|
+
for (const location of locations) {
|
|
1177
|
+
// yield* effectively works as flatMap here
|
|
1178
|
+
yield* getLocationCentroid(location);
|
|
1179
|
+
}
|
|
1180
|
+
})(),
|
|
1167
1181
|
);
|
|
1168
1182
|
|
|
1169
1183
|
// TODO: diff mode
|
|
1170
|
-
const circleColor = isDiffColorsRGBA(
|
|
1171
|
-
?
|
|
1172
|
-
:
|
|
1173
|
-
|
|
1174
|
-
const circleColors =
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
}),
|
|
1184
|
+
const circleColor = isDiffColorsRGBA(flowmapColors)
|
|
1185
|
+
? flowmapColors.positive.locationCircles.inner
|
|
1186
|
+
: flowmapColors.locationCircles.inner;
|
|
1187
|
+
|
|
1188
|
+
const circleColors = Uint8Array.from(
|
|
1189
|
+
(function* () {
|
|
1190
|
+
for (const location of locations) {
|
|
1191
|
+
yield* circleColor;
|
|
1192
|
+
}
|
|
1193
|
+
})(),
|
|
1194
|
+
);
|
|
1195
|
+
|
|
1196
|
+
const inCircleRadii = Float32Array.from(
|
|
1197
|
+
(function* () {
|
|
1198
|
+
for (const location of locations) {
|
|
1199
|
+
const id = getLocationId(location);
|
|
1200
|
+
yield locationIdsInViewport?.has(id) ? getInCircleSize(id) : 1.0;
|
|
1201
|
+
}
|
|
1202
|
+
})(),
|
|
1180
1203
|
);
|
|
1181
|
-
const outCircleRadii =
|
|
1182
|
-
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1204
|
+
const outCircleRadii = Float32Array.from(
|
|
1205
|
+
(function* () {
|
|
1206
|
+
for (const location of locations) {
|
|
1207
|
+
const id = getLocationId(location);
|
|
1208
|
+
yield locationIdsInViewport?.has(id) ? getOutCircleSize(id) : 1.0;
|
|
1209
|
+
}
|
|
1210
|
+
})(),
|
|
1186
1211
|
);
|
|
1187
1212
|
|
|
1188
|
-
const sourcePositions =
|
|
1189
|
-
|
|
1213
|
+
const sourcePositions = Float32Array.from(
|
|
1214
|
+
(function* () {
|
|
1215
|
+
for (const flow of flows) {
|
|
1216
|
+
yield* getCentroid(getFlowOriginId(flow));
|
|
1217
|
+
}
|
|
1218
|
+
})(),
|
|
1190
1219
|
);
|
|
1191
|
-
const targetPositions =
|
|
1192
|
-
|
|
1220
|
+
const targetPositions = Float32Array.from(
|
|
1221
|
+
(function* () {
|
|
1222
|
+
for (const flow of flows) {
|
|
1223
|
+
yield* getCentroid(getFlowDestId(flow));
|
|
1224
|
+
}
|
|
1225
|
+
})(),
|
|
1193
1226
|
);
|
|
1194
|
-
const thicknesses =
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1227
|
+
const thicknesses = Float32Array.from(
|
|
1228
|
+
(function* () {
|
|
1229
|
+
for (const flow of flows) {
|
|
1230
|
+
yield flowThicknessScale
|
|
1231
|
+
? flowThicknessScale(getFlowMagnitude(flow)) || 0
|
|
1232
|
+
: 0;
|
|
1233
|
+
}
|
|
1234
|
+
})(),
|
|
1198
1235
|
);
|
|
1199
|
-
const endpointOffsets =
|
|
1200
|
-
|
|
1201
|
-
const
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
Math.max(getInCircleSize(originId), getOutCircleSize(originId))
|
|
1205
|
-
Math.max(getInCircleSize(destId), getOutCircleSize(destId))
|
|
1206
|
-
|
|
1207
|
-
}),
|
|
1236
|
+
const endpointOffsets = Float32Array.from(
|
|
1237
|
+
(function* () {
|
|
1238
|
+
for (const flow of flows) {
|
|
1239
|
+
const originId = getFlowOriginId(flow);
|
|
1240
|
+
const destId = getFlowDestId(flow);
|
|
1241
|
+
yield Math.max(getInCircleSize(originId), getOutCircleSize(originId));
|
|
1242
|
+
yield Math.max(getInCircleSize(destId), getOutCircleSize(destId));
|
|
1243
|
+
}
|
|
1244
|
+
})(),
|
|
1208
1245
|
);
|
|
1209
|
-
const flowLineColors =
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1246
|
+
const flowLineColors = Uint8Array.from(
|
|
1247
|
+
(function* () {
|
|
1248
|
+
for (const flow of flows) {
|
|
1249
|
+
yield* flowColorScale(getFlowMagnitude(flow));
|
|
1250
|
+
}
|
|
1251
|
+
})(),
|
|
1213
1252
|
);
|
|
1214
1253
|
|
|
1215
1254
|
const staggeringValues = animationEnabled
|
|
1216
|
-
?
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1255
|
+
? Float32Array.from(
|
|
1256
|
+
(function* () {
|
|
1257
|
+
for (const f of flows) {
|
|
1258
|
+
// @ts-ignore
|
|
1259
|
+
yield new alea(`${getFlowOriginId(f)}-${getFlowDestId(f)}`)();
|
|
1260
|
+
}
|
|
1261
|
+
})(),
|
|
1221
1262
|
)
|
|
1222
1263
|
: undefined;
|
|
1223
1264
|
|
|
@@ -9,6 +9,7 @@ export interface FilterState {
|
|
|
9
9
|
export interface SettingsState {
|
|
10
10
|
animationEnabled: boolean;
|
|
11
11
|
fadeEnabled: boolean;
|
|
12
|
+
fadeOpacityEnabled: boolean;
|
|
12
13
|
locationTotalsEnabled: boolean;
|
|
13
14
|
adaptiveScalesEnabled: boolean;
|
|
14
15
|
clusteringEnabled: boolean;
|
|
@@ -17,9 +18,11 @@ export interface SettingsState {
|
|
|
17
18
|
darkMode: boolean;
|
|
18
19
|
fadeAmount: number;
|
|
19
20
|
colorScheme: string | undefined;
|
|
21
|
+
highlightColor: string;
|
|
22
|
+
maxTopFlowsDisplayNum: number;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
export interface
|
|
25
|
+
export interface FlowmapState {
|
|
23
26
|
filterState: FilterState;
|
|
24
27
|
settingsState: SettingsState;
|
|
25
28
|
viewport: ViewportProps;
|
package/src/colors.ts
CHANGED
|
@@ -26,9 +26,9 @@ import {
|
|
|
26
26
|
} from 'd3-scale-chromatic';
|
|
27
27
|
import {range} from 'd3-array';
|
|
28
28
|
import {scalePow, scaleSequential, scaleSequentialPow} from 'd3-scale';
|
|
29
|
-
import {interpolateRgbBasis} from 'd3-interpolate';
|
|
30
|
-
import {color as d3color, hcl} from 'd3-color';
|
|
31
|
-
import {SettingsState} from './
|
|
29
|
+
import {interpolateBasis, interpolateRgbBasis} from 'd3-interpolate';
|
|
30
|
+
import {color as d3color, hcl, rgb as colorRgb} from 'd3-color';
|
|
31
|
+
import {SettingsState} from './FlowmapState';
|
|
32
32
|
|
|
33
33
|
const DEFAULT_OUTLINE_COLOR = '#fff';
|
|
34
34
|
const DEFAULT_DIMMED_OPACITY = 0.4;
|
|
@@ -100,7 +100,7 @@ const getColorSteps = (interpolate: (x: number) => string) =>
|
|
|
100
100
|
.reverse();
|
|
101
101
|
|
|
102
102
|
const FLOW_MIN_COLOR = 'rgba(240,240,240,0.5)';
|
|
103
|
-
export const
|
|
103
|
+
export const GRAYISH = [FLOW_MIN_COLOR, ColorScheme.primary];
|
|
104
104
|
const schemeBluYl = [
|
|
105
105
|
'#f7feae',
|
|
106
106
|
'#b7e6a5',
|
|
@@ -134,7 +134,6 @@ export const schemeTeal = [
|
|
|
134
134
|
export const DEFAULT_COLOR_SCHEME = schemeTeal;
|
|
135
135
|
export const COLOR_SCHEMES: {[key: string]: string[]} = {
|
|
136
136
|
Blues: asScheme(schemeBlues),
|
|
137
|
-
BluesPale: BLUES_PALE,
|
|
138
137
|
BluGrn: [
|
|
139
138
|
'#c4e6c3',
|
|
140
139
|
'#96d2a4',
|
|
@@ -186,6 +185,7 @@ export const COLOR_SCHEMES: {[key: string]: string[]} = {
|
|
|
186
185
|
],
|
|
187
186
|
Emrld: schemeEmrld,
|
|
188
187
|
GnBu: asScheme(schemeGnBu),
|
|
188
|
+
Grayish: GRAYISH,
|
|
189
189
|
Greens: asScheme(schemeGreens),
|
|
190
190
|
Greys: asScheme(schemeGreys),
|
|
191
191
|
Inferno: getColorSteps(interpolateInferno),
|
|
@@ -330,7 +330,7 @@ const diffColors: DiffColors = {
|
|
|
330
330
|
outlineColor: 'rgb(230,233,237)',
|
|
331
331
|
};
|
|
332
332
|
|
|
333
|
-
export function
|
|
333
|
+
export function getFlowmapColors(
|
|
334
334
|
settingsState: SettingsState,
|
|
335
335
|
): Colors | DiffColors {
|
|
336
336
|
return getColors(
|
|
@@ -338,6 +338,7 @@ export function getFlowMapColors(
|
|
|
338
338
|
settingsState.colorScheme,
|
|
339
339
|
settingsState.darkMode,
|
|
340
340
|
settingsState.fadeEnabled,
|
|
341
|
+
settingsState.fadeOpacityEnabled,
|
|
341
342
|
settingsState.fadeAmount,
|
|
342
343
|
settingsState.animationEnabled,
|
|
343
344
|
);
|
|
@@ -348,6 +349,7 @@ export function getColors(
|
|
|
348
349
|
schemeKey: string | undefined,
|
|
349
350
|
darkMode: boolean,
|
|
350
351
|
fadeEnabled: boolean,
|
|
352
|
+
fadeOpacityEnabled: boolean,
|
|
351
353
|
fadeAmount: number,
|
|
352
354
|
animate: boolean,
|
|
353
355
|
): Colors | DiffColors {
|
|
@@ -390,13 +392,14 @@ export function getColors(
|
|
|
390
392
|
scheme = indices.map(
|
|
391
393
|
(c, i) => {
|
|
392
394
|
const color = colorScale(i);
|
|
393
|
-
const
|
|
394
|
-
if (color == null ||
|
|
395
|
+
const a = amount(i);
|
|
396
|
+
if (color == null || a == null) return '#000';
|
|
395
397
|
const col = hcl(color);
|
|
396
|
-
col.l = darkMode
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
col.l = darkMode ? col.l - col.l * a : col.l + (100 - col.l) * a;
|
|
399
|
+
col.c = col.c - col.c * (a / 4);
|
|
400
|
+
if (fadeOpacityEnabled) {
|
|
401
|
+
col.opacity = col.opacity * (1.0 - a);
|
|
402
|
+
}
|
|
400
403
|
return col.toString();
|
|
401
404
|
},
|
|
402
405
|
// interpolateRgbBasis([colorScale(i), darkMode ? '#000' : '#fff'])(amount(i))
|
|
@@ -417,15 +420,46 @@ export function getColors(
|
|
|
417
420
|
};
|
|
418
421
|
}
|
|
419
422
|
|
|
423
|
+
function interpolateRgbaBasis(colors: string[]) {
|
|
424
|
+
const spline = interpolateBasis;
|
|
425
|
+
const n = colors.length;
|
|
426
|
+
let r: any = new Array(n),
|
|
427
|
+
g: any = new Array(n),
|
|
428
|
+
b: any = new Array(n),
|
|
429
|
+
opacity: any = new Array(n),
|
|
430
|
+
i,
|
|
431
|
+
color: any;
|
|
432
|
+
for (i = 0; i < n; ++i) {
|
|
433
|
+
color = colorRgb(colors[i]);
|
|
434
|
+
r[i] = color.r || 0;
|
|
435
|
+
g[i] = color.g || 0;
|
|
436
|
+
b[i] = color.b || 0;
|
|
437
|
+
opacity[i] = color.opacity || 0;
|
|
438
|
+
}
|
|
439
|
+
r = spline(r);
|
|
440
|
+
g = spline(g);
|
|
441
|
+
b = spline(b);
|
|
442
|
+
opacity = spline(opacity);
|
|
443
|
+
// color.opacity = 1;
|
|
444
|
+
return function (t: number) {
|
|
445
|
+
color.r = r(t);
|
|
446
|
+
color.g = g(t);
|
|
447
|
+
color.b = b(t);
|
|
448
|
+
color.opacity = opacity(t);
|
|
449
|
+
return color + '';
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
420
453
|
export function createFlowColorScale(
|
|
421
454
|
domain: [number, number],
|
|
422
455
|
scheme: string[],
|
|
423
456
|
animate: boolean | undefined,
|
|
424
457
|
): ColorScale {
|
|
425
|
-
const scale = scaleSequentialPow(
|
|
458
|
+
const scale = scaleSequentialPow(interpolateRgbaBasis(scheme))
|
|
426
459
|
// @ts-ignore
|
|
427
460
|
.exponent(animate ? 1 / 2 : 1 / 3)
|
|
428
461
|
.domain(domain);
|
|
462
|
+
|
|
429
463
|
return (value: number) => colorAsRgba(scale(value));
|
|
430
464
|
}
|
|
431
465
|
|
|
@@ -516,7 +550,7 @@ export interface LocationCircleColors {
|
|
|
516
550
|
incoming?: string;
|
|
517
551
|
highlighted?: string;
|
|
518
552
|
empty?: string;
|
|
519
|
-
|
|
553
|
+
outlineEmptyMix?: number;
|
|
520
554
|
}
|
|
521
555
|
|
|
522
556
|
export interface LocationAreaColors {
|
|
@@ -563,7 +597,7 @@ export interface LocationCircleColorsRGBA {
|
|
|
563
597
|
incoming: RGBA;
|
|
564
598
|
highlighted: RGBA;
|
|
565
599
|
empty: RGBA;
|
|
566
|
-
|
|
600
|
+
outlineEmptyMix: number;
|
|
567
601
|
}
|
|
568
602
|
|
|
569
603
|
export interface LocationAreaColorsRGBA {
|
|
@@ -648,7 +682,7 @@ function getFlowAndCircleColors(
|
|
|
648
682
|
flowColorHighlighted,
|
|
649
683
|
),
|
|
650
684
|
empty: emptyColor,
|
|
651
|
-
|
|
685
|
+
outlineEmptyMix: inputColors?.locationCircles?.outlineEmptyMix ?? 0.4,
|
|
652
686
|
},
|
|
653
687
|
};
|
|
654
688
|
}
|