@flowmap.gl/data 8.0.0-alpha.0 → 8.0.0-alpha.4
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/FlowMapSelectors.d.ts +33 -6
- package/dist/FlowMapSelectors.d.ts.map +1 -1
- package/dist/FlowMapSelectors.js +101 -63
- package/dist/FlowMapState.d.ts +1 -0
- package/dist/FlowMapState.d.ts.map +1 -1
- package/dist/FlowMapState.js +1 -1
- package/dist/colors.d.ts +1 -1
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +37 -12
- package/dist/provider/LocalFlowMapDataProvider.d.ts.map +1 -1
- package/dist/provider/LocalFlowMapDataProvider.js +2 -2
- package/dist/util.d.ts +4 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +11 -4
- package/package.json +4 -3
- package/src/FlowMapSelectors.ts +195 -94
- package/src/FlowMapState.ts +1 -0
- package/src/colors.ts +43 -9
- package/src/provider/LocalFlowMapDataProvider.ts +1 -4
- package/src/util.ts +11 -3
package/src/FlowMapSelectors.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import {bounds} from '@mapbox/geo-viewport';
|
|
20
20
|
import {ascending, descending, extent, min} from 'd3-array';
|
|
21
21
|
import {nest} from 'd3-collection';
|
|
22
|
-
import {scaleLinear, scaleSqrt} from 'd3-scale';
|
|
22
|
+
import {ScaleLinear, scaleLinear, scaleSqrt} from 'd3-scale';
|
|
23
23
|
import KDBush from 'kdbush';
|
|
24
24
|
import {
|
|
25
25
|
createSelector,
|
|
@@ -36,6 +36,8 @@ import {
|
|
|
36
36
|
makeLocationWeightGetter,
|
|
37
37
|
} from './cluster/ClusterIndex';
|
|
38
38
|
import getColors, {
|
|
39
|
+
ColorsRGBA,
|
|
40
|
+
DiffColorsRGBA,
|
|
39
41
|
getColorsRGBA,
|
|
40
42
|
getDiffColorsRGBA,
|
|
41
43
|
getFlowColorScale,
|
|
@@ -66,7 +68,6 @@ import {
|
|
|
66
68
|
LocationFilterMode,
|
|
67
69
|
LocationTotals,
|
|
68
70
|
} from './types';
|
|
69
|
-
import {flatMap} from './util';
|
|
70
71
|
|
|
71
72
|
const MAX_CLUSTER_ZOOM_LEVEL = 20;
|
|
72
73
|
const NUMBER_OF_FLOWS_TO_DISPLAY = 5000;
|
|
@@ -124,6 +125,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
124
125
|
props: FlowMapData<L, F>,
|
|
125
126
|
) => state.settingsState.fadeEnabled;
|
|
126
127
|
|
|
128
|
+
getFadeOpacityEnabled: Selector<L, F, boolean> = (
|
|
129
|
+
state: FlowMapState,
|
|
130
|
+
props: FlowMapData<L, F>,
|
|
131
|
+
) => state.settingsState.fadeOpacityEnabled;
|
|
132
|
+
|
|
127
133
|
getFadeAmount: Selector<L, F, number> = (
|
|
128
134
|
state: FlowMapState,
|
|
129
135
|
props: FlowMapData<L, F>,
|
|
@@ -485,6 +491,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
485
491
|
this.getColorSchemeKey,
|
|
486
492
|
this.getDarkMode,
|
|
487
493
|
this.getFadeEnabled,
|
|
494
|
+
this.getFadeOpacityEnabled,
|
|
488
495
|
this.getFadeAmount,
|
|
489
496
|
this.getAnimate,
|
|
490
497
|
getColors,
|
|
@@ -560,7 +567,7 @@ export default class FlowMapSelectors<L, F> {
|
|
|
560
567
|
},
|
|
561
568
|
);
|
|
562
569
|
|
|
563
|
-
|
|
570
|
+
getFlowMagnitudeExtent: Selector<L, F, [number, number] | undefined> =
|
|
564
571
|
createSelector(
|
|
565
572
|
this.getSortedAggregatedFilteredFlows,
|
|
566
573
|
this.getSelectedLocationsSet,
|
|
@@ -775,10 +782,9 @@ export default class FlowMapSelectors<L, F> {
|
|
|
775
782
|
);
|
|
776
783
|
|
|
777
784
|
getLocationIdsInViewport: Selector<L, F, Set<string> | undefined> =
|
|
778
|
-
|
|
779
|
-
createSelectorCreator<Set<string> | undefined>(
|
|
780
|
-
// @ts-ignore
|
|
785
|
+
createSelectorCreator(
|
|
781
786
|
defaultMemoize,
|
|
787
|
+
// @ts-ignore
|
|
782
788
|
(
|
|
783
789
|
s1: Set<string> | undefined,
|
|
784
790
|
s2: Set<string> | undefined,
|
|
@@ -899,10 +905,10 @@ export default class FlowMapSelectors<L, F> {
|
|
|
899
905
|
},
|
|
900
906
|
);
|
|
901
907
|
|
|
902
|
-
|
|
908
|
+
_getFlowMagnitudeExtent = (
|
|
903
909
|
state: FlowMapState,
|
|
904
910
|
props: FlowMapData<L, F>,
|
|
905
|
-
): [number, number] | undefined {
|
|
911
|
+
): [number, number] | undefined => {
|
|
906
912
|
if (state.settingsState.adaptiveScalesEnabled) {
|
|
907
913
|
const flows = this.getFlowsForFlowMapLayer(state, props);
|
|
908
914
|
if (flows) {
|
|
@@ -912,9 +918,9 @@ export default class FlowMapSelectors<L, F> {
|
|
|
912
918
|
return undefined;
|
|
913
919
|
}
|
|
914
920
|
} else {
|
|
915
|
-
return this.
|
|
921
|
+
return this.getFlowMagnitudeExtent(state, props);
|
|
916
922
|
}
|
|
917
|
-
}
|
|
923
|
+
};
|
|
918
924
|
|
|
919
925
|
getLocationMaxAbsTotalGetter = createSelector(
|
|
920
926
|
this.getLocationTotals,
|
|
@@ -930,41 +936,46 @@ export default class FlowMapSelectors<L, F> {
|
|
|
930
936
|
},
|
|
931
937
|
);
|
|
932
938
|
|
|
933
|
-
getFlowThicknessScale = (
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
const maxLocationCircleSize = this.getMaxLocationCircleSize(state, props);
|
|
950
|
-
const {locationTotalsEnabled} = state.settingsState;
|
|
951
|
-
if (!locationTotalsEnabled) {
|
|
952
|
-
return () => maxLocationCircleSize;
|
|
953
|
-
}
|
|
939
|
+
getFlowThicknessScale = createSelector(
|
|
940
|
+
this.getFlowMagnitudeExtent,
|
|
941
|
+
(magnitudeExtent) => {
|
|
942
|
+
if (!magnitudeExtent) return undefined;
|
|
943
|
+
return scaleLinear()
|
|
944
|
+
.range([0.025, 0.5])
|
|
945
|
+
.domain([
|
|
946
|
+
0,
|
|
947
|
+
// should support diff mode too
|
|
948
|
+
Math.max.apply(
|
|
949
|
+
null,
|
|
950
|
+
magnitudeExtent.map((x: number | undefined) => Math.abs(x || 0)),
|
|
951
|
+
),
|
|
952
|
+
]);
|
|
953
|
+
},
|
|
954
|
+
);
|
|
954
955
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
)
|
|
966
|
-
|
|
967
|
-
|
|
956
|
+
getCircleSizeScale = createSelector(
|
|
957
|
+
this.getMaxLocationCircleSize,
|
|
958
|
+
this.getLocationTotalsEnabled,
|
|
959
|
+
this.getLocationTotalsExtent,
|
|
960
|
+
(maxLocationCircleSize, locationTotalsEnabled, locationTotalsExtent) => {
|
|
961
|
+
if (!locationTotalsEnabled) {
|
|
962
|
+
return () => maxLocationCircleSize;
|
|
963
|
+
}
|
|
964
|
+
if (!locationTotalsExtent) return undefined;
|
|
965
|
+
return scaleSqrt()
|
|
966
|
+
.range([0, maxLocationCircleSize])
|
|
967
|
+
.domain([
|
|
968
|
+
0,
|
|
969
|
+
// should support diff mode too
|
|
970
|
+
Math.max.apply(
|
|
971
|
+
null,
|
|
972
|
+
locationTotalsExtent.map((x: number | undefined) =>
|
|
973
|
+
Math.abs(x || 0),
|
|
974
|
+
),
|
|
975
|
+
),
|
|
976
|
+
]);
|
|
977
|
+
},
|
|
978
|
+
);
|
|
968
979
|
|
|
969
980
|
getInCircleSizeGetter = createSelector(
|
|
970
981
|
this.getCircleSizeScale,
|
|
@@ -1063,9 +1074,76 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1063
1074
|
);
|
|
1064
1075
|
});
|
|
1065
1076
|
|
|
1077
|
+
getLayersData: Selector<L, F, LayersData> = createSelector(
|
|
1078
|
+
this.getLocationsForFlowMapLayer,
|
|
1079
|
+
this.getFlowsForFlowMapLayer,
|
|
1080
|
+
this.getFlowMapColorsRGBA,
|
|
1081
|
+
this.getLocationsForFlowMapLayerById,
|
|
1082
|
+
this.getLocationIdsInViewport,
|
|
1083
|
+
this.getInCircleSizeGetter,
|
|
1084
|
+
this.getOutCircleSizeGetter,
|
|
1085
|
+
this.getFlowThicknessScale,
|
|
1086
|
+
this.getAnimate,
|
|
1087
|
+
(
|
|
1088
|
+
locations,
|
|
1089
|
+
flows,
|
|
1090
|
+
flowMapColors,
|
|
1091
|
+
locationsById,
|
|
1092
|
+
locationIdsInViewport,
|
|
1093
|
+
getInCircleSize,
|
|
1094
|
+
getOutCircleSize,
|
|
1095
|
+
flowThicknessScale,
|
|
1096
|
+
animationEnabled,
|
|
1097
|
+
) => {
|
|
1098
|
+
return this._prepareLayersData(
|
|
1099
|
+
locations,
|
|
1100
|
+
flows,
|
|
1101
|
+
flowMapColors,
|
|
1102
|
+
locationsById,
|
|
1103
|
+
locationIdsInViewport,
|
|
1104
|
+
getInCircleSize,
|
|
1105
|
+
getOutCircleSize,
|
|
1106
|
+
flowThicknessScale,
|
|
1107
|
+
animationEnabled,
|
|
1108
|
+
);
|
|
1109
|
+
},
|
|
1110
|
+
);
|
|
1111
|
+
|
|
1066
1112
|
prepareLayersData(state: FlowMapState, props: FlowMapData<L, F>): LayersData {
|
|
1067
1113
|
const locations = this.getLocationsForFlowMapLayer(state, props) || [];
|
|
1068
1114
|
const flows = this.getFlowsForFlowMapLayer(state, props) || [];
|
|
1115
|
+
const flowMapColors = this.getFlowMapColorsRGBA(state, props);
|
|
1116
|
+
const locationsById = this.getLocationsForFlowMapLayerById(state, props);
|
|
1117
|
+
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
1118
|
+
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
1119
|
+
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
1120
|
+
const flowThicknessScale = this.getFlowThicknessScale(state, props);
|
|
1121
|
+
return this._prepareLayersData(
|
|
1122
|
+
locations,
|
|
1123
|
+
flows,
|
|
1124
|
+
flowMapColors,
|
|
1125
|
+
locationsById,
|
|
1126
|
+
locationIdsInViewport,
|
|
1127
|
+
getInCircleSize,
|
|
1128
|
+
getOutCircleSize,
|
|
1129
|
+
flowThicknessScale,
|
|
1130
|
+
state.settingsState.animationEnabled,
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
_prepareLayersData(
|
|
1135
|
+
locations: (L | ClusterNode)[] | undefined,
|
|
1136
|
+
flows: (F | AggregateFlow)[] | undefined,
|
|
1137
|
+
flowMapColors: DiffColorsRGBA | ColorsRGBA,
|
|
1138
|
+
locationsById: Map<string, L | ClusterNode> | undefined,
|
|
1139
|
+
locationIdsInViewport: Set<string> | undefined,
|
|
1140
|
+
getInCircleSize: (locationId: string) => number,
|
|
1141
|
+
getOutCircleSize: (locationId: string) => number,
|
|
1142
|
+
flowThicknessScale: ScaleLinear<number, number, never> | undefined,
|
|
1143
|
+
animationEnabled: boolean,
|
|
1144
|
+
): LayersData {
|
|
1145
|
+
if (!locations) locations = [];
|
|
1146
|
+
if (!flows) flows = [];
|
|
1069
1147
|
const {
|
|
1070
1148
|
getFlowOriginId,
|
|
1071
1149
|
getFlowDestId,
|
|
@@ -1074,21 +1152,11 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1074
1152
|
getLocationCentroid,
|
|
1075
1153
|
} = this.accessors;
|
|
1076
1154
|
|
|
1077
|
-
const flowMapColors = this.getFlowMapColorsRGBA(state, props);
|
|
1078
|
-
const {settingsState} = state;
|
|
1079
|
-
|
|
1080
|
-
const locationsById = this.getLocationsForFlowMapLayerById(state, props);
|
|
1081
1155
|
const getCentroid = (id: string) => {
|
|
1082
1156
|
const loc = locationsById?.get(id);
|
|
1083
1157
|
return loc ? getLocationCentroid(loc) : [0, 0];
|
|
1084
1158
|
};
|
|
1085
1159
|
|
|
1086
|
-
const locationIdsInViewport = this.getLocationIdsInViewport(state, props);
|
|
1087
|
-
const getInCircleSize = this.getInCircleSizeGetter(state, props);
|
|
1088
|
-
const getOutCircleSize = this.getOutCircleSizeGetter(state, props);
|
|
1089
|
-
|
|
1090
|
-
const flowThicknessScale = this.getFlowThicknessScale(state, props);
|
|
1091
|
-
|
|
1092
1160
|
const flowMagnitudeExtent = extent(flows, (f) => getFlowMagnitude(f)) as [
|
|
1093
1161
|
number,
|
|
1094
1162
|
number,
|
|
@@ -1099,8 +1167,14 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1099
1167
|
false,
|
|
1100
1168
|
);
|
|
1101
1169
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1170
|
+
// Using yield here helps to avoid creating intermediary arrays
|
|
1171
|
+
const circlePositions = Float32Array.from(
|
|
1172
|
+
(function* () {
|
|
1173
|
+
for (const location of locations) {
|
|
1174
|
+
// yield* effectively does same as flatMap here
|
|
1175
|
+
yield* getLocationCentroid(location);
|
|
1176
|
+
}
|
|
1177
|
+
})(),
|
|
1104
1178
|
);
|
|
1105
1179
|
|
|
1106
1180
|
// TODO: diff mode
|
|
@@ -1108,53 +1182,80 @@ export default class FlowMapSelectors<L, F> {
|
|
|
1108
1182
|
? flowMapColors.positive.locationCircles.inner
|
|
1109
1183
|
: flowMapColors.locationCircles.inner;
|
|
1110
1184
|
|
|
1111
|
-
const circleColors =
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
}),
|
|
1185
|
+
const circleColors = Uint8Array.from(
|
|
1186
|
+
(function* () {
|
|
1187
|
+
for (const location of locations) {
|
|
1188
|
+
yield* circleColor;
|
|
1189
|
+
}
|
|
1190
|
+
})(),
|
|
1191
|
+
);
|
|
1192
|
+
|
|
1193
|
+
const inCircleRadii = Float32Array.from(
|
|
1194
|
+
(function* () {
|
|
1195
|
+
for (const location of locations) {
|
|
1196
|
+
const id = getLocationId(location);
|
|
1197
|
+
yield locationIdsInViewport?.has(id) ? getInCircleSize(id) : 1.0;
|
|
1198
|
+
}
|
|
1199
|
+
})(),
|
|
1117
1200
|
);
|
|
1118
|
-
const outCircleRadii =
|
|
1119
|
-
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1201
|
+
const outCircleRadii = Float32Array.from(
|
|
1202
|
+
(function* () {
|
|
1203
|
+
for (const location of locations) {
|
|
1204
|
+
const id = getLocationId(location);
|
|
1205
|
+
yield locationIdsInViewport?.has(id) ? getOutCircleSize(id) : 1.0;
|
|
1206
|
+
}
|
|
1207
|
+
})(),
|
|
1123
1208
|
);
|
|
1124
1209
|
|
|
1125
|
-
const sourcePositions =
|
|
1126
|
-
|
|
1210
|
+
const sourcePositions = Float32Array.from(
|
|
1211
|
+
(function* () {
|
|
1212
|
+
for (const flow of flows) {
|
|
1213
|
+
yield* getCentroid(getFlowOriginId(flow));
|
|
1214
|
+
}
|
|
1215
|
+
})(),
|
|
1127
1216
|
);
|
|
1128
|
-
const targetPositions =
|
|
1129
|
-
|
|
1217
|
+
const targetPositions = Float32Array.from(
|
|
1218
|
+
(function* () {
|
|
1219
|
+
for (const flow of flows) {
|
|
1220
|
+
yield* getCentroid(getFlowDestId(flow));
|
|
1221
|
+
}
|
|
1222
|
+
})(),
|
|
1130
1223
|
);
|
|
1131
|
-
const thicknesses =
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1224
|
+
const thicknesses = Float32Array.from(
|
|
1225
|
+
(function* () {
|
|
1226
|
+
for (const flow of flows) {
|
|
1227
|
+
yield flowThicknessScale
|
|
1228
|
+
? flowThicknessScale(getFlowMagnitude(flow)) || 0
|
|
1229
|
+
: 0;
|
|
1230
|
+
}
|
|
1231
|
+
})(),
|
|
1135
1232
|
);
|
|
1136
|
-
const endpointOffsets =
|
|
1137
|
-
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
Math.max(getInCircleSize(originId), getOutCircleSize(originId))
|
|
1142
|
-
Math.max(getInCircleSize(destId), getOutCircleSize(destId))
|
|
1143
|
-
|
|
1144
|
-
}),
|
|
1233
|
+
const endpointOffsets = Float32Array.from(
|
|
1234
|
+
(function* () {
|
|
1235
|
+
for (const flow of flows) {
|
|
1236
|
+
const originId = getFlowOriginId(flow);
|
|
1237
|
+
const destId = getFlowDestId(flow);
|
|
1238
|
+
yield Math.max(getInCircleSize(originId), getOutCircleSize(originId));
|
|
1239
|
+
yield Math.max(getInCircleSize(destId), getOutCircleSize(destId));
|
|
1240
|
+
}
|
|
1241
|
+
})(),
|
|
1145
1242
|
);
|
|
1146
|
-
const flowLineColors =
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1243
|
+
const flowLineColors = Uint8Array.from(
|
|
1244
|
+
(function* () {
|
|
1245
|
+
for (const flow of flows) {
|
|
1246
|
+
yield* flowColorScale(getFlowMagnitude(flow));
|
|
1247
|
+
}
|
|
1248
|
+
})(),
|
|
1150
1249
|
);
|
|
1151
1250
|
|
|
1152
|
-
const staggeringValues =
|
|
1153
|
-
?
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1251
|
+
const staggeringValues = animationEnabled
|
|
1252
|
+
? Float32Array.from(
|
|
1253
|
+
(function* () {
|
|
1254
|
+
for (const flow of flows) {
|
|
1255
|
+
// @ts-ignore
|
|
1256
|
+
yield new alea(`${getFlowOriginId(f)}-${getFlowDestId(f)}`)();
|
|
1257
|
+
}
|
|
1258
|
+
})(),
|
|
1158
1259
|
)
|
|
1159
1260
|
: undefined;
|
|
1160
1261
|
|
package/src/FlowMapState.ts
CHANGED
package/src/colors.ts
CHANGED
|
@@ -26,8 +26,8 @@ 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';
|
|
29
|
+
import {interpolateBasis, interpolateRgbBasis} from 'd3-interpolate';
|
|
30
|
+
import {color as d3color, hcl, rgb as colorRgb} from 'd3-color';
|
|
31
31
|
import {SettingsState} from './FlowMapState';
|
|
32
32
|
|
|
33
33
|
const DEFAULT_OUTLINE_COLOR = '#fff';
|
|
@@ -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
|
|
|
@@ -66,10 +66,7 @@ export default class LocalFlowMapDataProvider<L, F>
|
|
|
66
66
|
if (!this.flowMapState || !this.flowMapData) {
|
|
67
67
|
return undefined;
|
|
68
68
|
}
|
|
69
|
-
return this.selectors.
|
|
70
|
-
this.flowMapState,
|
|
71
|
-
this.flowMapData,
|
|
72
|
-
);
|
|
69
|
+
return this.selectors.getLayersData(this.flowMapState, this.flowMapData);
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
async getLocationById(id: string): Promise<L | Cluster | undefined> {
|
package/src/util.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {createSelectorCreator, defaultMemoize} from 'reselect';
|
|
2
|
+
|
|
3
|
+
export const createDebugSelector = createSelectorCreator(defaultMemoize, {
|
|
4
|
+
equalityCheck: (previousVal: any, currentVal: any) => {
|
|
5
|
+
const rv = currentVal === previousVal;
|
|
6
|
+
if (!rv) {
|
|
7
|
+
console.log('Selector param value changed', currentVal);
|
|
8
|
+
}
|
|
9
|
+
return rv;
|
|
10
|
+
},
|
|
11
|
+
});
|