sea-chart 2.0.25 → 2.0.27
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/assets/css/sea-chart-d3-tooltip.css +1 -1
- package/dist/components/tooltip/index.js +2 -1
- package/dist/components/types-dialog/index.js +1 -1
- package/dist/services/map-json.js +1 -1
- package/dist/view/wrapper/chart-component.js +163 -28
- package/dist/view/wrapper/index.js +28 -0
- package/dist/view/wrapper/map-bubble.js +267 -0
- package/dist/view/wrapper/map-world-bubble.js +266 -0
- package/dist/view/wrapper/map-world.js +279 -0
- package/dist/view/wrapper/map.js +267 -0
- package/package.json +3 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.sea-chart-d3-tooltip-container {
|
|
2
2
|
position: absolute;
|
|
3
3
|
transform: translate(-9999px, -9999px);
|
|
4
|
-
transition: transform 0.
|
|
4
|
+
transition: transform 0.1s;
|
|
5
5
|
background-color: rgb(255, 255, 255);
|
|
6
6
|
box-shadow: rgba(196, 175, 175, 0.1) 0px 0px 1px 1px;
|
|
7
7
|
border-radius: 3px;
|
|
@@ -68,7 +68,8 @@ const ToolTip = _ref => {
|
|
|
68
68
|
ref: tooltipRef,
|
|
69
69
|
className: "sea-chart-d3-tooltip-container",
|
|
70
70
|
style: {
|
|
71
|
-
transform: "translate(".concat(position.offsetX, "px, ").concat(position.offsetY, "px)")
|
|
71
|
+
transform: "translate(".concat(position.offsetX, "px, ").concat(position.offsetY, "px)"),
|
|
72
|
+
display: position.offsetX === -9999 ? 'none' : 'block'
|
|
72
73
|
}
|
|
73
74
|
}, title && /*#__PURE__*/_react.default.createElement("div", {
|
|
74
75
|
className: "sea-chart-d3-tooltip-title"
|
|
@@ -69,7 +69,7 @@ const TypesDialog = _ref => {
|
|
|
69
69
|
}, [onChange, selectedType, onToggle]);
|
|
70
70
|
const handleFilterTypes = (0, _react.useCallback)(() => {
|
|
71
71
|
if (hideTypeToggle) {
|
|
72
|
-
const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram', 'Bar_chart', 'Line_chart', 'Area', 'Pie_chart', 'Scatter_chart', 'Combination_chart'].includes(item.name));
|
|
72
|
+
const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram', 'Bar_chart', 'Line_chart', 'Area', 'Pie_chart', 'Scatter_chart', 'Combination_chart', 'Map'].includes(item.name));
|
|
73
73
|
return newChartTypes;
|
|
74
74
|
}
|
|
75
75
|
return _constants.CHART_TYPES;
|
|
@@ -75,7 +75,7 @@ function getMapJsonQueryUrl(mapLevel, mapLocation) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
function handleLoadedMapJson(url, mapJson) {
|
|
78
|
-
const isValid = mapJson && mapJson.features;
|
|
78
|
+
const isValid = mapJson && ((mapJson === null || mapJson === void 0 ? void 0 : mapJson.type) === 'Topology' && (mapJson === null || mapJson === void 0 ? void 0 : mapJson.objects) || (mapJson === null || mapJson === void 0 ? void 0 : mapJson.type) === 'FeatureCollection' && (mapJson === null || mapJson === void 0 ? void 0 : mapJson.features));
|
|
79
79
|
if (isValid) {
|
|
80
80
|
setMapJson(url, mapJson);
|
|
81
81
|
return mapJson;
|
|
@@ -645,22 +645,62 @@ class ChartComponent extends _react.Component {
|
|
|
645
645
|
return _intl.default.get(name) || name;
|
|
646
646
|
}
|
|
647
647
|
};
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
648
|
+
// set continuous legend
|
|
649
|
+
this.setContinuousLegend = _ref => {
|
|
650
|
+
var _this$chart$node2;
|
|
651
|
+
let {
|
|
652
|
+
previewType,
|
|
653
|
+
theme,
|
|
654
|
+
colorRange = [],
|
|
655
|
+
legendDirection,
|
|
656
|
+
legendSize,
|
|
657
|
+
legendTextRange,
|
|
658
|
+
bubbleColor,
|
|
659
|
+
type
|
|
660
|
+
} = _ref;
|
|
661
|
+
const {
|
|
662
|
+
width: chartWidth,
|
|
663
|
+
height: chartHeight,
|
|
664
|
+
insertPadding
|
|
665
|
+
} = this.chartBoundingClientRect;
|
|
666
|
+
const legendRectWidth = legendDirection === 'vertical' ? 12 : Math.min(legendSize * 100, chartWidth - insertPadding * 2);
|
|
667
|
+
const legendRectHeight = legendDirection === 'vertical' ? Math.min(legendSize * 100, chartHeight - insertPadding * 2) : 12;
|
|
668
|
+
const legendTextOffset = 2;
|
|
669
|
+
const legendTextHeightSpace = legendDirection === 'vertical' ? 0 : 14 + legendTextOffset;
|
|
670
|
+
if (![_constants.CHART_TYPE.MAP_BUBBLE, _constants.CHART_TYPE.WORLD_MAP_BUBBLE].includes(type)) {
|
|
671
|
+
var _this$chart$node;
|
|
672
|
+
// add linearGradient
|
|
673
|
+
const gradient = this.chart.append('defs').attr('class', 'linear-gradient-wrapper').append('linearGradient').attr("id", "gradient-".concat((_this$chart$node = this.chart.node()) === null || _this$chart$node === void 0 ? void 0 : _this$chart$node.id, "-").concat(previewType)).attr("x1", '0%').attr("y1", '0%').attr("x2", legendDirection === 'vertical' ? '0%' : '100%').attr("y2", legendDirection === 'vertical' ? '100%' : '0%');
|
|
674
|
+
gradient.append('stop').attr('offset', '0%').attr('stop-color', "".concat(colorRange[0]));
|
|
675
|
+
gradient.append('stop').attr('offset', '50%').attr('stop-color', "".concat(colorRange[4]));
|
|
676
|
+
gradient.append('stop').attr('offset', '100%').attr('stop-color', "".concat(colorRange[8]));
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// add legend
|
|
680
|
+
const continuousLegendWrapper = this.chart.append('g').attr('class', 'legend-continuous-wrapper').attr('transform', "translate(".concat(insertPadding, ", ").concat(chartHeight - legendRectHeight - legendTextHeightSpace, ")"));
|
|
681
|
+
continuousLegendWrapper.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('fill', [_constants.CHART_TYPE.MAP_BUBBLE, _constants.CHART_TYPE.WORLD_MAP_BUBBLE].includes(type) ? bubbleColor : "url(#gradient-".concat((_this$chart$node2 = this.chart.node()) === null || _this$chart$node2 === void 0 ? void 0 : _this$chart$node2.id, "-").concat(previewType, ")")).call(g => {
|
|
682
|
+
if ([_constants.CHART_TYPE.MAP_BUBBLE, _constants.CHART_TYPE.WORLD_MAP_BUBBLE].includes(type)) {
|
|
683
|
+
continuousLegendWrapper.append('polygon').attr('points', "0,0 ".concat(legendRectWidth - 0.5, ",0 0,").concat(legendRectHeight - 0.5)).attr('fill', '#fff').attr('stroke', '#fff');
|
|
655
684
|
}
|
|
656
685
|
});
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
686
|
+
continuousLegendWrapper.append('text').attr('class', 'range-start').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('fill', theme.labelColor).text(legendTextRange[0]).call(g => {
|
|
687
|
+
const {
|
|
688
|
+
height
|
|
689
|
+
} = g.node().getBoundingClientRect();
|
|
690
|
+
g.attr('x', legendDirection === 'vertical' ? legendRectWidth + legendTextOffset : legendTextOffset);
|
|
691
|
+
g.attr('y', legendDirection === 'vertical' ? height : height + legendRectHeight);
|
|
692
|
+
});
|
|
693
|
+
continuousLegendWrapper.append('text').attr('class', 'range-end').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('fill', theme.labelColor).text(legendTextRange[1]).call(g => {
|
|
694
|
+
const {
|
|
695
|
+
width,
|
|
696
|
+
height
|
|
697
|
+
} = g.node().getBoundingClientRect();
|
|
698
|
+
g.attr('x', legendDirection === 'vertical' ? legendRectWidth + legendTextOffset : legendRectWidth - width);
|
|
699
|
+
g.attr('y', legendDirection === 'vertical' ? legendRectHeight - legendTextOffset : height + legendRectHeight);
|
|
660
700
|
});
|
|
661
701
|
};
|
|
662
702
|
// set legend
|
|
663
|
-
this.setLegend =
|
|
703
|
+
this.setLegend = _ref2 => {
|
|
664
704
|
var _chart$config, _chart$config2, _chart$config3;
|
|
665
705
|
let {
|
|
666
706
|
legendName,
|
|
@@ -670,7 +710,7 @@ class ChartComponent extends _react.Component {
|
|
|
670
710
|
colorScale,
|
|
671
711
|
groupColumn,
|
|
672
712
|
chart
|
|
673
|
-
} =
|
|
713
|
+
} = _ref2;
|
|
674
714
|
if (!this.chart) return;
|
|
675
715
|
this.legendConfig = {
|
|
676
716
|
legendRectWidth: (chart === null || chart === void 0 ? void 0 : (_chart$config = chart.config) === null || _chart$config === void 0 ? void 0 : _chart$config.type) === _constants.CHART_TYPE.SCATTER ? 8 : 20,
|
|
@@ -698,6 +738,7 @@ class ChartComponent extends _react.Component {
|
|
|
698
738
|
bottomLegendSpace
|
|
699
739
|
} = this.chartBoundingClientRect;
|
|
700
740
|
const groupsData = this.getLegendDataGroups(legendData);
|
|
741
|
+
if (groupsData.length === 0) return;
|
|
701
742
|
const legendWrapper = this.chart.append('g').attr('class', 'legend-wrapper');
|
|
702
743
|
|
|
703
744
|
// legend offset bottom and When there is only one line of legend, it is displayed in the center (for scatter chart)
|
|
@@ -788,14 +829,14 @@ class ChartComponent extends _react.Component {
|
|
|
788
829
|
});
|
|
789
830
|
}
|
|
790
831
|
};
|
|
791
|
-
this.renderLegend =
|
|
832
|
+
this.renderLegend = _ref3 => {
|
|
792
833
|
let {
|
|
793
834
|
legendWrapper,
|
|
794
835
|
groupData,
|
|
795
836
|
colorScale,
|
|
796
837
|
theme,
|
|
797
838
|
text
|
|
798
|
-
} =
|
|
839
|
+
} = _ref3;
|
|
799
840
|
const {
|
|
800
841
|
legendItemPaddingTop,
|
|
801
842
|
legendItemTextPaddingTop,
|
|
@@ -821,15 +862,15 @@ class ChartComponent extends _react.Component {
|
|
|
821
862
|
d3.select(item).remove();
|
|
822
863
|
});
|
|
823
864
|
}
|
|
824
|
-
legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName',
|
|
825
|
-
let [groupName] = _ref3;
|
|
826
|
-
return groupName;
|
|
827
|
-
}).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref4 => {
|
|
865
|
+
legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName', _ref4 => {
|
|
828
866
|
let [groupName] = _ref4;
|
|
867
|
+
return groupName;
|
|
868
|
+
}).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref5 => {
|
|
869
|
+
let [groupName] = _ref5;
|
|
829
870
|
if (colorScale) return colorScale(groupName);
|
|
830
871
|
return this.colorMap[groupName] || _constants.CHART_STYLE_COLORS[0];
|
|
831
|
-
}).attr('data-text',
|
|
832
|
-
let [groupName] =
|
|
872
|
+
}).attr('data-text', _ref6 => {
|
|
873
|
+
let [groupName] = _ref6;
|
|
833
874
|
return groupName;
|
|
834
875
|
}).call(g => {
|
|
835
876
|
// Add text
|
|
@@ -1021,6 +1062,20 @@ class ChartComponent extends _react.Component {
|
|
|
1021
1062
|
d3.select(legendItem).attr('opacity', 1);
|
|
1022
1063
|
});
|
|
1023
1064
|
};
|
|
1065
|
+
this.sortLegend = (result, groupColumn, legendName) => {
|
|
1066
|
+
result.forEach(item => {
|
|
1067
|
+
const option = groupColumn.data.options.find(option => option.name === item[legendName]);
|
|
1068
|
+
if (option !== null && option !== void 0 && option.id) {
|
|
1069
|
+
item['group_name_id'] = option.id;
|
|
1070
|
+
item['oldName'] = item.name;
|
|
1071
|
+
item.name = item['group_name_id'];
|
|
1072
|
+
}
|
|
1073
|
+
});
|
|
1074
|
+
_utils.BaseUtils.sortCharts(result, groupColumn, 'name');
|
|
1075
|
+
result.forEach(item => {
|
|
1076
|
+
item.name = item['oldName'];
|
|
1077
|
+
});
|
|
1078
|
+
};
|
|
1024
1079
|
// theta is pie or ring chart
|
|
1025
1080
|
this.setLegendForTheta = function (legendName) {
|
|
1026
1081
|
let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
|
|
@@ -1080,6 +1135,86 @@ class ChartComponent extends _react.Component {
|
|
|
1080
1135
|
});
|
|
1081
1136
|
this.formatedDataByName = formattedItems;
|
|
1082
1137
|
};
|
|
1138
|
+
this.formatMapStatisticData = (statisticData, mapData, type) => {
|
|
1139
|
+
if (!statisticData) return [];
|
|
1140
|
+
if (!mapData.features) return [];
|
|
1141
|
+
let statisticNewData = [];
|
|
1142
|
+
let sum = 0;
|
|
1143
|
+
|
|
1144
|
+
// Modify the map json data of type Topology
|
|
1145
|
+
mapData.features.forEach(feature => {
|
|
1146
|
+
if (feature.properties.fullname) {
|
|
1147
|
+
feature.properties.name = feature.properties.fullname;
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1150
|
+
statisticData.forEach((item, index) => {
|
|
1151
|
+
if (item && item.name) {
|
|
1152
|
+
let matchFeature = mapData.features.find(feature => feature.properties.name.indexOf(item.name) > -1);
|
|
1153
|
+
if (matchFeature) {
|
|
1154
|
+
statisticNewData.push({
|
|
1155
|
+
name: matchFeature.properties.name,
|
|
1156
|
+
value: item.value || 0
|
|
1157
|
+
});
|
|
1158
|
+
if (type === 'map_bubble') {
|
|
1159
|
+
sum += item.value;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
});
|
|
1164
|
+
if (type === 'map_bubble') {
|
|
1165
|
+
statisticNewData.sum = sum;
|
|
1166
|
+
}
|
|
1167
|
+
return statisticNewData;
|
|
1168
|
+
};
|
|
1169
|
+
this.formatWorldMapStatisticData = (statisticData, mapData, type) => {
|
|
1170
|
+
if (!statisticData) return [];
|
|
1171
|
+
if (!mapData.features) return [];
|
|
1172
|
+
const reg = /^([A-Za-z])/;
|
|
1173
|
+
const countryMap = new Map();
|
|
1174
|
+
mapData.features.forEach(item => {
|
|
1175
|
+
countryMap.set(item.properties.name, item.properties.name_cn);
|
|
1176
|
+
countryMap.set(item.properties.name_cn, item.properties.name);
|
|
1177
|
+
});
|
|
1178
|
+
let sum = 0;
|
|
1179
|
+
let statisticNewData = [];
|
|
1180
|
+
statisticData.forEach(item => {
|
|
1181
|
+
if (item && item.name) {
|
|
1182
|
+
let nameType, name, name_cn;
|
|
1183
|
+
if (reg.test(item.name)) {
|
|
1184
|
+
nameType = 'en';
|
|
1185
|
+
name = item.name;
|
|
1186
|
+
name_cn = countryMap.get(name);
|
|
1187
|
+
} else {
|
|
1188
|
+
nameType = 'zh-cn';
|
|
1189
|
+
name = countryMap.get(item.name);
|
|
1190
|
+
name_cn = item.name;
|
|
1191
|
+
}
|
|
1192
|
+
const value = item.value;
|
|
1193
|
+
if (name_cn && name) {
|
|
1194
|
+
const existedData = statisticNewData.find(i => i.name === name);
|
|
1195
|
+
if (existedData) {
|
|
1196
|
+
existedData.value += value;
|
|
1197
|
+
existedData.formatted_value = parseInt(existedData.formatted_value) + parseInt(item.formatted_value) + '';
|
|
1198
|
+
} else {
|
|
1199
|
+
statisticNewData.push({
|
|
1200
|
+
name_cn,
|
|
1201
|
+
name,
|
|
1202
|
+
nameType,
|
|
1203
|
+
value: value || 0,
|
|
1204
|
+
formatted_value: item.formatted_value + ''
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
if (type === _constants.CHART_TYPE.WORLD_MAP_BUBBLE) {
|
|
1208
|
+
sum += item.value;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
if (type === _constants.CHART_TYPE.WORLD_MAP_BUBBLE) {
|
|
1214
|
+
statisticNewData.sum = sum;
|
|
1215
|
+
}
|
|
1216
|
+
return statisticNewData;
|
|
1217
|
+
};
|
|
1083
1218
|
this.getToolTipSettings = (isGroup, summaryColumn, y_axis_summary_method, useSingleSelectColumnColor) => {
|
|
1084
1219
|
const obj = {
|
|
1085
1220
|
showMarkers: false,
|
|
@@ -1235,7 +1370,7 @@ class ChartComponent extends _react.Component {
|
|
|
1235
1370
|
annotationWrapper.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
|
|
1236
1371
|
});
|
|
1237
1372
|
};
|
|
1238
|
-
this.addLabelToRectTop =
|
|
1373
|
+
this.addLabelToRectTop = _ref7 => {
|
|
1239
1374
|
let {
|
|
1240
1375
|
container,
|
|
1241
1376
|
x,
|
|
@@ -1244,7 +1379,7 @@ class ChartComponent extends _react.Component {
|
|
|
1244
1379
|
theme,
|
|
1245
1380
|
label_font_size,
|
|
1246
1381
|
text
|
|
1247
|
-
} =
|
|
1382
|
+
} = _ref7;
|
|
1248
1383
|
d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('y', Number(y) - 10).attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
1249
1384
|
const {
|
|
1250
1385
|
width
|
|
@@ -1252,7 +1387,7 @@ class ChartComponent extends _react.Component {
|
|
|
1252
1387
|
g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
|
|
1253
1388
|
});
|
|
1254
1389
|
};
|
|
1255
|
-
this.addLabelToRectRight =
|
|
1390
|
+
this.addLabelToRectRight = _ref8 => {
|
|
1256
1391
|
let {
|
|
1257
1392
|
container,
|
|
1258
1393
|
x,
|
|
@@ -1262,7 +1397,7 @@ class ChartComponent extends _react.Component {
|
|
|
1262
1397
|
theme,
|
|
1263
1398
|
label_font_size,
|
|
1264
1399
|
text
|
|
1265
|
-
} =
|
|
1400
|
+
} = _ref8;
|
|
1266
1401
|
d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('x', Number(x) + Number(xWidth) + 10).attr('y', Number(y)).attr('fill', theme.labelColor).attr('dominant-baseline', 'hanging').attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
1267
1402
|
if (g.node()) {
|
|
1268
1403
|
var _g$node;
|
|
@@ -1273,7 +1408,7 @@ class ChartComponent extends _react.Component {
|
|
|
1273
1408
|
}
|
|
1274
1409
|
});
|
|
1275
1410
|
};
|
|
1276
|
-
this.addLabelToRectCenter =
|
|
1411
|
+
this.addLabelToRectCenter = _ref9 => {
|
|
1277
1412
|
let {
|
|
1278
1413
|
chartType,
|
|
1279
1414
|
container,
|
|
@@ -1284,7 +1419,7 @@ class ChartComponent extends _react.Component {
|
|
|
1284
1419
|
theme,
|
|
1285
1420
|
label_font_size,
|
|
1286
1421
|
text
|
|
1287
|
-
} =
|
|
1422
|
+
} = _ref9;
|
|
1288
1423
|
d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
1289
1424
|
const {
|
|
1290
1425
|
width,
|
|
@@ -1326,13 +1461,13 @@ class ChartComponent extends _react.Component {
|
|
|
1326
1461
|
}
|
|
1327
1462
|
};
|
|
1328
1463
|
// Use clipPath to make rectangle rounded corners
|
|
1329
|
-
this.addClipPath =
|
|
1464
|
+
this.addClipPath = _ref10 => {
|
|
1330
1465
|
let {
|
|
1331
1466
|
rect,
|
|
1332
1467
|
parentNode,
|
|
1333
1468
|
attr,
|
|
1334
1469
|
rectId
|
|
1335
|
-
} =
|
|
1470
|
+
} = _ref10;
|
|
1336
1471
|
const {
|
|
1337
1472
|
borderRadius
|
|
1338
1473
|
} = this.chartBoundingClientRect;
|
|
@@ -30,6 +30,10 @@ var _ring = _interopRequireDefault(require("./ring"));
|
|
|
30
30
|
var _scatter = _interopRequireDefault(require("./scatter"));
|
|
31
31
|
var _basicNumberCard = _interopRequireDefault(require("./basic-number-card"));
|
|
32
32
|
var _combination = _interopRequireDefault(require("./combination"));
|
|
33
|
+
var _map = _interopRequireDefault(require("./map"));
|
|
34
|
+
var _mapBubble = _interopRequireDefault(require("./map-bubble"));
|
|
35
|
+
var _mapWorld = _interopRequireDefault(require("./map-world"));
|
|
36
|
+
var _mapWorldBubble = _interopRequireDefault(require("./map-world-bubble"));
|
|
33
37
|
var _trend = _interopRequireDefault(require("./trend"));
|
|
34
38
|
var _tableElement = _interopRequireDefault(require("./table-element"));
|
|
35
39
|
const Wrapper = _ref => {
|
|
@@ -251,6 +255,30 @@ const Wrapper = _ref => {
|
|
|
251
255
|
canvasStyle: canvasStyle
|
|
252
256
|
}));
|
|
253
257
|
}
|
|
258
|
+
case _constants.CHART_TYPE.MAP:
|
|
259
|
+
{
|
|
260
|
+
return /*#__PURE__*/_react.default.createElement(_map.default, Object.assign({}, baseProps, {
|
|
261
|
+
canvasStyle: canvasStyle
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
case _constants.CHART_TYPE.MAP_BUBBLE:
|
|
265
|
+
{
|
|
266
|
+
return /*#__PURE__*/_react.default.createElement(_mapBubble.default, Object.assign({}, baseProps, {
|
|
267
|
+
canvasStyle: canvasStyle
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
case _constants.CHART_TYPE.WORLD_MAP:
|
|
271
|
+
{
|
|
272
|
+
return /*#__PURE__*/_react.default.createElement(_mapWorld.default, Object.assign({}, baseProps, {
|
|
273
|
+
canvasStyle: canvasStyle
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
case _constants.CHART_TYPE.WORLD_MAP_BUBBLE:
|
|
277
|
+
{
|
|
278
|
+
return /*#__PURE__*/_react.default.createElement(_mapWorldBubble.default, Object.assign({}, baseProps, {
|
|
279
|
+
canvasStyle: canvasStyle
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
254
282
|
case _constants.CHART_TYPE.BASIC_NUMBER_CARD:
|
|
255
283
|
{
|
|
256
284
|
return /*#__PURE__*/_react.default.createElement(_basicNumberCard.default, Object.assign({}, baseProps, {
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
var _react = _interopRequireDefault(require("react"));
|
|
10
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
+
var _lodashEs = require("lodash-es");
|
|
12
|
+
var d3 = _interopRequireWildcard(require("d3"));
|
|
13
|
+
var _topojson = require("topojson");
|
|
14
|
+
var _dtableUtils = require("dtable-utils");
|
|
15
|
+
var _constants = require("../../constants");
|
|
16
|
+
var _utils = require("../../utils");
|
|
17
|
+
var _context = _interopRequireDefault(require("../../context"));
|
|
18
|
+
var _mapJson = _interopRequireDefault(require("../../services/map-json"));
|
|
19
|
+
var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
|
|
20
|
+
var _chartComponent = _interopRequireDefault(require("./chart-component"));
|
|
21
|
+
class MapBubble extends _chartComponent.default {
|
|
22
|
+
constructor(props) {
|
|
23
|
+
super(props);
|
|
24
|
+
this.handleResize = () => {
|
|
25
|
+
this.chart.node() && this.chart.node().remove();
|
|
26
|
+
this.createChart();
|
|
27
|
+
this.drawChart();
|
|
28
|
+
};
|
|
29
|
+
this.createChart = () => {
|
|
30
|
+
const {
|
|
31
|
+
chart
|
|
32
|
+
} = this.props;
|
|
33
|
+
const initConfig = {
|
|
34
|
+
insertPadding: 30
|
|
35
|
+
};
|
|
36
|
+
this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
|
|
37
|
+
};
|
|
38
|
+
this.drawChart = async () => {
|
|
39
|
+
let {
|
|
40
|
+
result: data,
|
|
41
|
+
chart
|
|
42
|
+
} = this.props;
|
|
43
|
+
if (!Array.isArray(data)) return;
|
|
44
|
+
const {
|
|
45
|
+
map_location,
|
|
46
|
+
map_level = _constants.MAP_LEVEL.COUNTRY,
|
|
47
|
+
type
|
|
48
|
+
} = chart.config;
|
|
49
|
+
const mediaUrl = _context.default.getSetting('mediaUrl');
|
|
50
|
+
const mapJson = await (0, _mapJson.default)(map_level, map_location, mediaUrl);
|
|
51
|
+
if (!mapJson) return;
|
|
52
|
+
const newMapJson = map_level === _constants.MAP_LEVEL.COUNTRY ? (0, _topojson.feature)(mapJson, mapJson.objects) : mapJson;
|
|
53
|
+
const statisticNewData = this.formatMapStatisticData(data, newMapJson, type);
|
|
54
|
+
this.draw(statisticNewData, newMapJson);
|
|
55
|
+
};
|
|
56
|
+
this.showTooltip = event => {
|
|
57
|
+
const title = event.currentTarget.getAttribute('data-name');
|
|
58
|
+
const value = Number(event.currentTarget.getAttribute('data-value'));
|
|
59
|
+
const {
|
|
60
|
+
offsetX,
|
|
61
|
+
offsetY
|
|
62
|
+
} = event;
|
|
63
|
+
const newTooltipData = {
|
|
64
|
+
title,
|
|
65
|
+
items: [{
|
|
66
|
+
color: '',
|
|
67
|
+
name: '数量',
|
|
68
|
+
value
|
|
69
|
+
}]
|
|
70
|
+
};
|
|
71
|
+
this.setState({
|
|
72
|
+
tooltipData: newTooltipData
|
|
73
|
+
});
|
|
74
|
+
this.setState({
|
|
75
|
+
toolTipPosition: {
|
|
76
|
+
offsetX,
|
|
77
|
+
offsetY
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
this.moveTooltip = event => {
|
|
82
|
+
const {
|
|
83
|
+
offsetX,
|
|
84
|
+
offsetY
|
|
85
|
+
} = event;
|
|
86
|
+
this.setState({
|
|
87
|
+
toolTipPosition: {
|
|
88
|
+
offsetX,
|
|
89
|
+
offsetY
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
this.hiddenTooltip = event => {
|
|
94
|
+
this.setState({
|
|
95
|
+
toolTipPosition: null
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
this.draw = (data, mapJson) => {
|
|
99
|
+
const {
|
|
100
|
+
chart,
|
|
101
|
+
globalTheme,
|
|
102
|
+
canvasStyle
|
|
103
|
+
} = this.props;
|
|
104
|
+
const theme = _constants.CHART_THEME_COLOR[globalTheme];
|
|
105
|
+
const {
|
|
106
|
+
legend_size,
|
|
107
|
+
legend_direction,
|
|
108
|
+
summary_method,
|
|
109
|
+
type,
|
|
110
|
+
bubble_color = '#2a67d1'
|
|
111
|
+
} = chart.config;
|
|
112
|
+
const {
|
|
113
|
+
width: chartWidth,
|
|
114
|
+
height: chartHeight,
|
|
115
|
+
insertPadding
|
|
116
|
+
} = this.chartBoundingClientRect;
|
|
117
|
+
|
|
118
|
+
// 1. Setting up projection
|
|
119
|
+
const projection = d3.geoMercator().fitSize([chartWidth - insertPadding, chartHeight - insertPadding], mapJson);
|
|
120
|
+
|
|
121
|
+
// 2. Generate a path based on projection
|
|
122
|
+
const pathGenerator = d3.geoPath(projection);
|
|
123
|
+
|
|
124
|
+
// 3. Rendering map
|
|
125
|
+
this.chart.append('g').attr('class', 'map-wrapper').selectAll().data(mapJson.features).join('g').append('path').attr('d', d => {
|
|
126
|
+
return pathGenerator(d);
|
|
127
|
+
}).attr('stroke-width', 1).attr('stroke', '#bdbdbd').attr('stroke-opacity', 1).attr('fill', '#e2e2e2').attr('opacity', 1).attr('data-name', d => d.properties.name);
|
|
128
|
+
|
|
129
|
+
// draw bubble circle
|
|
130
|
+
this.drawCircle(data, mapJson, pathGenerator);
|
|
131
|
+
|
|
132
|
+
// draw legend
|
|
133
|
+
const columnData = this.getColumnData();
|
|
134
|
+
this.setContinuousLegend({
|
|
135
|
+
previewType: canvasStyle.previewType,
|
|
136
|
+
theme,
|
|
137
|
+
legendDirection: legend_direction,
|
|
138
|
+
legendSize: legend_size,
|
|
139
|
+
legendTextRange: [_utils.BaseUtils.getSummaryValueDisplayString(columnData, d3.min(data, d => d.value), summary_method), _utils.BaseUtils.getSummaryValueDisplayString(columnData, d3.max(data, d => d.value), summary_method)],
|
|
140
|
+
type,
|
|
141
|
+
bubbleColor: bubble_color
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
this.handleAcitveAndInActiveState = (state, event, highlightedBorderColor) => {
|
|
145
|
+
if (state === 'active') {
|
|
146
|
+
d3.select(event.currentTarget).transition().duration(this.transitionDuration).attr('fill-opacity', 0.9);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
d3.select(event.currentTarget).transition().duration(this.transitionDuration).attr('fill-opacity', 0.6);
|
|
150
|
+
};
|
|
151
|
+
this.getColumnData = () => {
|
|
152
|
+
const {
|
|
153
|
+
chart
|
|
154
|
+
} = this.props;
|
|
155
|
+
const {
|
|
156
|
+
summary_type,
|
|
157
|
+
summary_column_key,
|
|
158
|
+
table_id
|
|
159
|
+
} = chart.config;
|
|
160
|
+
let columnData = _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
|
|
161
|
+
if (summary_type === _constants.CHART_SUMMARY_TYPE.ADVANCED) {
|
|
162
|
+
const table = (0, _dtableUtils.getTableById)(table_id);
|
|
163
|
+
const summaryColumn = (0, _dtableUtils.getTableColumnByKey)(table, summary_column_key) || {};
|
|
164
|
+
columnData = summaryColumn.data || _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
|
|
165
|
+
}
|
|
166
|
+
return columnData;
|
|
167
|
+
};
|
|
168
|
+
this.drawCircle = (data, mapData, geoPath) => {
|
|
169
|
+
const {
|
|
170
|
+
chart
|
|
171
|
+
} = this.props;
|
|
172
|
+
const {
|
|
173
|
+
bubble_color = '#2a67d1'
|
|
174
|
+
} = chart.config;
|
|
175
|
+
const circleData = [];
|
|
176
|
+
mapData.features.forEach(item => {
|
|
177
|
+
const curName = item.properties.name;
|
|
178
|
+
const curData = data.find(item => item.name.includes(curName));
|
|
179
|
+
if (curData) {
|
|
180
|
+
circleData.push({
|
|
181
|
+
feature: item,
|
|
182
|
+
value: curData.value,
|
|
183
|
+
name: curName
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
const bubbleWrapper = this.chart.append('g').attr('class', 'bubble-wrapper');
|
|
188
|
+
circleData.forEach(_ref => {
|
|
189
|
+
let {
|
|
190
|
+
feature,
|
|
191
|
+
value,
|
|
192
|
+
name
|
|
193
|
+
} = _ref;
|
|
194
|
+
const centroid = geoPath.centroid(feature);
|
|
195
|
+
if (centroid && centroid[0] && centroid[1]) {
|
|
196
|
+
bubbleWrapper.append('circle').attr('cx', centroid[0]).attr('cy', centroid[1]).attr('r', () => {
|
|
197
|
+
const percent = value / data.sum;
|
|
198
|
+
let size = percent * 100;
|
|
199
|
+
return size;
|
|
200
|
+
}).attr('fill', bubble_color).attr('fill-opacity', 0.6).attr('stroke', bubble_color).attr('stroke-opacity', 0.9).attr('data-value', value).attr('data-name', name).on('click', event => {
|
|
201
|
+
const name = event.target.getAttribute('data-name');
|
|
202
|
+
const newData = data.find(item => item.name.includes(name));
|
|
203
|
+
newData && this.props.toggleRecords(newData);
|
|
204
|
+
}).on('mouseover', event => {
|
|
205
|
+
this.showTooltip(event);
|
|
206
|
+
this.handleAcitveAndInActiveState('active', event);
|
|
207
|
+
}).on('mousemove', event => {
|
|
208
|
+
this.moveTooltip(event);
|
|
209
|
+
}).on('mouseleave', event => {
|
|
210
|
+
this.hiddenTooltip(event);
|
|
211
|
+
this.handleAcitveAndInActiveState('inActive', event);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
this.chart = null;
|
|
217
|
+
this.state = {
|
|
218
|
+
tooltipData: null,
|
|
219
|
+
toolTipPosition: null
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
componentDidMount() {
|
|
223
|
+
this.createChart();
|
|
224
|
+
this.drawChart();
|
|
225
|
+
this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
|
|
226
|
+
window.addEventListener('resize', this.debouncedHandleResize);
|
|
227
|
+
}
|
|
228
|
+
componentDidUpdate(prevProps) {
|
|
229
|
+
super.componentDidUpdate(prevProps);
|
|
230
|
+
if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
|
|
231
|
+
this.createChart();
|
|
232
|
+
this.drawChart();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
componentWillUnmount() {
|
|
236
|
+
this.chart.node() && this.chart.node().remove();
|
|
237
|
+
window.removeEventListener('resize', this.debouncedHandleResize);
|
|
238
|
+
}
|
|
239
|
+
render() {
|
|
240
|
+
const {
|
|
241
|
+
tooltipData,
|
|
242
|
+
toolTipPosition
|
|
243
|
+
} = this.state;
|
|
244
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
245
|
+
ref: ref => this.container = ref,
|
|
246
|
+
className: "sea-chart-container"
|
|
247
|
+
}, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
|
|
248
|
+
tooltipData: tooltipData,
|
|
249
|
+
toolTipPosition: toolTipPosition,
|
|
250
|
+
chart: this.chart
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
MapBubble.propTypes = {
|
|
255
|
+
canvasStyle: _propTypes.default.object,
|
|
256
|
+
chart: _propTypes.default.object,
|
|
257
|
+
groupbyColumn: _propTypes.default.object,
|
|
258
|
+
columnGroupbyColumn: _propTypes.default.object,
|
|
259
|
+
summaryColumn: _propTypes.default.object,
|
|
260
|
+
result: _propTypes.default.array,
|
|
261
|
+
tables: _propTypes.default.array,
|
|
262
|
+
globalTheme: _propTypes.default.string,
|
|
263
|
+
chartColorTheme: _propTypes.default.string,
|
|
264
|
+
toggleRecords: _propTypes.default.func,
|
|
265
|
+
customRender: _propTypes.default.func
|
|
266
|
+
};
|
|
267
|
+
var _default = exports.default = MapBubble;
|