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.
@@ -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.2s;
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
- this.sortLegend = (result, groupColumn, legendName) => {
649
- result.forEach(item => {
650
- const option = groupColumn.data.options.find(option => option.name === item[legendName]);
651
- if (option !== null && option !== void 0 && option.id) {
652
- item['group_name_id'] = option.id;
653
- item['oldName'] = item.name;
654
- item.name = item['group_name_id'];
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
- _utils.BaseUtils.sortCharts(result, groupColumn, 'name');
658
- result.forEach(item => {
659
- item.name = item['oldName'];
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 = _ref => {
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
- } = _ref;
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 = _ref2 => {
832
+ this.renderLegend = _ref3 => {
792
833
  let {
793
834
  legendWrapper,
794
835
  groupData,
795
836
  colorScale,
796
837
  theme,
797
838
  text
798
- } = _ref2;
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', _ref3 => {
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', _ref5 => {
832
- let [groupName] = _ref5;
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 = _ref6 => {
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
- } = _ref6;
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 = _ref7 => {
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
- } = _ref7;
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 = _ref8 => {
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
- } = _ref8;
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 = _ref9 => {
1464
+ this.addClipPath = _ref10 => {
1330
1465
  let {
1331
1466
  rect,
1332
1467
  parentNode,
1333
1468
  attr,
1334
1469
  rectId
1335
- } = _ref9;
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;