sea-chart 2.0.26 → 2.0.28

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.
@@ -70,8 +70,6 @@ const TypesDialog = _ref => {
70
70
  const handleFilterTypes = (0, _react.useCallback)(() => {
71
71
  if (hideTypeToggle) {
72
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
- const newMapChildren = newChartTypes[newChartTypes.length - 1].children.slice(0, 2);
74
- newChartTypes[newChartTypes.length - 1].children = newMapChildren;
75
73
  return newChartTypes;
76
74
  }
77
75
  return _constants.CHART_TYPES;
@@ -667,7 +667,7 @@ class ChartComponent extends _react.Component {
667
667
  const legendRectHeight = legendDirection === 'vertical' ? Math.min(legendSize * 100, chartHeight - insertPadding * 2) : 12;
668
668
  const legendTextOffset = 2;
669
669
  const legendTextHeightSpace = legendDirection === 'vertical' ? 0 : 14 + legendTextOffset;
670
- if (type !== _constants.CHART_TYPE.MAP_BUBBLE) {
670
+ if (![_constants.CHART_TYPE.MAP_BUBBLE, _constants.CHART_TYPE.WORLD_MAP_BUBBLE].includes(type)) {
671
671
  var _this$chart$node;
672
672
  // add linearGradient
673
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%');
@@ -677,9 +677,9 @@ class ChartComponent extends _react.Component {
677
677
  }
678
678
 
679
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', type === _constants.CHART_TYPE.MAP_BUBBLE ? 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 (type === _constants.CHART_TYPE.MAP_BUBBLE) {
680
+ const continuousLegendWrapper = this.chart.append('g').attr('class', 'legend-continuous-wrapper').attr('transform', "translate(0, ".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
683
  continuousLegendWrapper.append('polygon').attr('points', "0,0 ".concat(legendRectWidth - 0.5, ",0 0,").concat(legendRectHeight - 0.5)).attr('fill', '#fff').attr('stroke', '#fff');
684
684
  }
685
685
  });
@@ -1140,6 +1140,13 @@ class ChartComponent extends _react.Component {
1140
1140
  if (!mapData.features) return [];
1141
1141
  let statisticNewData = [];
1142
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
+ });
1143
1150
  statisticData.forEach((item, index) => {
1144
1151
  if (item && item.name) {
1145
1152
  let matchFeature = mapData.features.find(feature => feature.properties.name.indexOf(item.name) > -1);
@@ -1159,6 +1166,55 @@ class ChartComponent extends _react.Component {
1159
1166
  }
1160
1167
  return statisticNewData;
1161
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
+ };
1162
1218
  this.getToolTipSettings = (isGroup, summaryColumn, y_axis_summary_method, useSingleSelectColumnColor) => {
1163
1219
  const obj = {
1164
1220
  showMarkers: false,
@@ -32,6 +32,8 @@ var _basicNumberCard = _interopRequireDefault(require("./basic-number-card"));
32
32
  var _combination = _interopRequireDefault(require("./combination"));
33
33
  var _map = _interopRequireDefault(require("./map"));
34
34
  var _mapBubble = _interopRequireDefault(require("./map-bubble"));
35
+ var _mapWorld = _interopRequireDefault(require("./map-world"));
36
+ var _mapWorldBubble = _interopRequireDefault(require("./map-world-bubble"));
35
37
  var _trend = _interopRequireDefault(require("./trend"));
36
38
  var _tableElement = _interopRequireDefault(require("./table-element"));
37
39
  const Wrapper = _ref => {
@@ -265,6 +267,18 @@ const Wrapper = _ref => {
265
267
  canvasStyle: canvasStyle
266
268
  }));
267
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
+ }
268
282
  case _constants.CHART_TYPE.BASIC_NUMBER_CARD:
269
283
  {
270
284
  return /*#__PURE__*/_react.default.createElement(_basicNumberCard.default, Object.assign({}, baseProps, {
@@ -49,8 +49,9 @@ class MapBubble extends _chartComponent.default {
49
49
  const mediaUrl = _context.default.getSetting('mediaUrl');
50
50
  const mapJson = await (0, _mapJson.default)(map_level, map_location, mediaUrl);
51
51
  if (!mapJson) return;
52
- const statisticNewData = this.formatMapStatisticData(data, mapJson, type);
53
- this.draw(statisticNewData, mapJson);
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);
54
55
  };
55
56
  this.showTooltip = event => {
56
57
  const title = event.currentTarget.getAttribute('data-name');
@@ -102,7 +103,6 @@ class MapBubble extends _chartComponent.default {
102
103
  } = this.props;
103
104
  const theme = _constants.CHART_THEME_COLOR[globalTheme];
104
105
  const {
105
- map_level = _constants.MAP_LEVEL.COUNTRY,
106
106
  legend_size,
107
107
  legend_direction,
108
108
  summary_method,
@@ -114,21 +114,20 @@ class MapBubble extends _chartComponent.default {
114
114
  height: chartHeight,
115
115
  insertPadding
116
116
  } = this.chartBoundingClientRect;
117
- const newMapData = map_level === _constants.MAP_LEVEL.COUNTRY ? (0, _topojson.feature)(mapJson, mapJson.objects) : mapJson;
118
117
 
119
118
  // 1. Setting up projection
120
- const projection = d3.geoMercator().fitSize([chartWidth - insertPadding, chartHeight - insertPadding], newMapData);
119
+ const projection = d3.geoMercator().fitExtent([[insertPadding, insertPadding], [chartWidth - insertPadding, chartHeight - insertPadding]], mapJson);
121
120
 
122
121
  // 2. Generate a path based on projection
123
122
  const pathGenerator = d3.geoPath(projection);
124
123
 
125
124
  // 3. Rendering map
126
- this.chart.append('g').attr('class', 'map-wrapper').selectAll().data(newMapData.features).join('g').append('path').attr('d', d => {
125
+ this.chart.append('g').attr('class', 'map-wrapper').selectAll().data(mapJson.features).join('g').append('path').attr('d', d => {
127
126
  return pathGenerator(d);
128
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);
129
128
 
130
129
  // draw bubble circle
131
- this.drawCircle(data, newMapData, pathGenerator);
130
+ this.drawCircle(data, mapJson, pathGenerator);
132
131
 
133
132
  // draw legend
134
133
  const columnData = this.getColumnData();
@@ -0,0 +1,266 @@
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
+ type
46
+ } = chart.config;
47
+ const mediaUrl = _context.default.getSetting('mediaUrl');
48
+ const mapJson = await (0, _mapJson.default)(_constants.MAP_LEVEL.WORLD, '', mediaUrl);
49
+ if (!mapJson) return;
50
+ const newMapJson = (0, _topojson.feature)(mapJson, mapJson.objects);
51
+ const statisticNewData = this.formatWorldMapStatisticData(data, newMapJson, type);
52
+ this.draw(statisticNewData, newMapJson);
53
+ };
54
+ this.showTooltip = (event, data) => {
55
+ const curData = data.find(item => item.name.includes(event.currentTarget.getAttribute('data-name')));
56
+ const title = curData.nameType === 'en' ? curData.name : curData.name_cn;
57
+ const value = Number(event.currentTarget.getAttribute('data-value'));
58
+ const {
59
+ offsetX,
60
+ offsetY
61
+ } = event;
62
+ const newTooltipData = {
63
+ title,
64
+ items: [{
65
+ color: '',
66
+ name: '数量',
67
+ value
68
+ }]
69
+ };
70
+ this.setState({
71
+ tooltipData: newTooltipData
72
+ });
73
+ this.setState({
74
+ toolTipPosition: {
75
+ offsetX,
76
+ offsetY
77
+ }
78
+ });
79
+ };
80
+ this.moveTooltip = event => {
81
+ const {
82
+ offsetX,
83
+ offsetY
84
+ } = event;
85
+ this.setState({
86
+ toolTipPosition: {
87
+ offsetX,
88
+ offsetY
89
+ }
90
+ });
91
+ };
92
+ this.hiddenTooltip = event => {
93
+ this.setState({
94
+ toolTipPosition: null
95
+ });
96
+ };
97
+ this.draw = (data, mapJson) => {
98
+ const {
99
+ chart,
100
+ globalTheme,
101
+ canvasStyle
102
+ } = this.props;
103
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
104
+ const {
105
+ legend_size,
106
+ legend_direction,
107
+ summary_method,
108
+ type,
109
+ bubble_color
110
+ } = chart.config;
111
+ const {
112
+ width: chartWidth,
113
+ height: chartHeight,
114
+ insertPadding
115
+ } = this.chartBoundingClientRect;
116
+
117
+ // 1. Setting up projection
118
+ const projection = d3.geoMercator().fitExtent([[insertPadding, insertPadding], [chartWidth - insertPadding, chartHeight - insertPadding]], mapJson);
119
+
120
+ // 2. Generate a path based on projection
121
+ const pathGenerator = d3.geoPath(projection);
122
+
123
+ // 3. Rendering map
124
+ this.chart.append('g').attr('class', 'map-wrapper').selectAll().data(mapJson.features).join('g').append('path').attr('d', d => {
125
+ return pathGenerator(d);
126
+ }).attr('stroke-width', 1).attr('stroke', '#bdbdbd').attr('stroke-opacity', 1).attr('fill', '#e2e2e2').attr('opacity', 1).attr('data-name', d => d.properties.name);
127
+
128
+ // draw bubble circle
129
+ this.drawCircle(data, mapJson, pathGenerator);
130
+
131
+ // draw legend
132
+ const columnData = this.getColumnData();
133
+ this.setContinuousLegend({
134
+ previewType: canvasStyle.previewType,
135
+ theme,
136
+ legendDirection: legend_direction,
137
+ legendSize: legend_size,
138
+ 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)],
139
+ type,
140
+ bubbleColor: bubble_color || '#2a67d1'
141
+ });
142
+ };
143
+ this.handleAcitveAndInActiveState = (state, event, highlightedBorderColor) => {
144
+ if (state === 'active') {
145
+ d3.select(event.currentTarget).transition().duration(this.transitionDuration).attr('fill-opacity', 0.9);
146
+ return;
147
+ }
148
+ d3.select(event.currentTarget).transition().duration(this.transitionDuration).attr('fill-opacity', 0.6);
149
+ };
150
+ this.getColumnData = () => {
151
+ const {
152
+ chart
153
+ } = this.props;
154
+ const {
155
+ summary_type,
156
+ summary_column_key,
157
+ table_id
158
+ } = chart.config;
159
+ let columnData = _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
160
+ if (summary_type === _constants.CHART_SUMMARY_TYPE.ADVANCED) {
161
+ const table = (0, _dtableUtils.getTableById)(table_id);
162
+ const summaryColumn = (0, _dtableUtils.getTableColumnByKey)(table, summary_column_key) || {};
163
+ columnData = summaryColumn.data || _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
164
+ }
165
+ return columnData;
166
+ };
167
+ this.drawCircle = (data, mapData, geoPath) => {
168
+ const {
169
+ chart
170
+ } = this.props;
171
+ const {
172
+ bubble_color
173
+ } = chart.config;
174
+ const circleData = [];
175
+ mapData.features.forEach(item => {
176
+ const curName = item.properties.name;
177
+ const curData = data.find(item => item.name.includes(curName));
178
+ if (curData) {
179
+ circleData.push({
180
+ feature: item,
181
+ value: curData.value,
182
+ name: curName
183
+ });
184
+ }
185
+ });
186
+ const bubbleWrapper = this.chart.append('g').attr('class', 'bubble-wrapper');
187
+ circleData.forEach(_ref => {
188
+ let {
189
+ feature,
190
+ value,
191
+ name
192
+ } = _ref;
193
+ const centroid = geoPath.centroid(feature);
194
+ if (centroid && centroid[0] && centroid[1]) {
195
+ bubbleWrapper.append('circle').attr('cx', centroid[0]).attr('cy', centroid[1]).attr('r', () => {
196
+ const percent = value / data.sum;
197
+ let size = percent * 100;
198
+ return size;
199
+ }).attr('fill', bubble_color || '#2a67d1').attr('fill-opacity', 0.6).attr('stroke', bubble_color || '#2a67d1').attr('stroke-opacity', 0.9).attr('data-value', value).attr('data-name', name).on('click', event => {
200
+ const name = event.target.getAttribute('data-name');
201
+ const newData = data.find(item => item.name.includes(name));
202
+ newData && this.props.toggleRecords(newData);
203
+ }).on('mouseover', event => {
204
+ this.showTooltip(event, data);
205
+ this.handleAcitveAndInActiveState('active', event);
206
+ }).on('mousemove', event => {
207
+ this.moveTooltip(event);
208
+ }).on('mouseleave', event => {
209
+ this.hiddenTooltip(event);
210
+ this.handleAcitveAndInActiveState('inActive', event);
211
+ });
212
+ }
213
+ });
214
+ };
215
+ this.chart = null;
216
+ this.state = {
217
+ tooltipData: null,
218
+ toolTipPosition: null
219
+ };
220
+ }
221
+ componentDidMount() {
222
+ this.createChart();
223
+ this.drawChart();
224
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
225
+ window.addEventListener('resize', this.debouncedHandleResize);
226
+ }
227
+ componentDidUpdate(prevProps) {
228
+ super.componentDidUpdate(prevProps);
229
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
230
+ this.createChart();
231
+ this.drawChart();
232
+ }
233
+ }
234
+ componentWillUnmount() {
235
+ this.chart.node() && this.chart.node().remove();
236
+ window.removeEventListener('resize', this.debouncedHandleResize);
237
+ }
238
+ render() {
239
+ const {
240
+ tooltipData,
241
+ toolTipPosition
242
+ } = this.state;
243
+ return /*#__PURE__*/_react.default.createElement("div", {
244
+ ref: ref => this.container = ref,
245
+ className: "sea-chart-container"
246
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
247
+ tooltipData: tooltipData,
248
+ toolTipPosition: toolTipPosition,
249
+ chart: this.chart
250
+ }));
251
+ }
252
+ }
253
+ MapBubble.propTypes = {
254
+ canvasStyle: _propTypes.default.object,
255
+ chart: _propTypes.default.object,
256
+ groupbyColumn: _propTypes.default.object,
257
+ columnGroupbyColumn: _propTypes.default.object,
258
+ summaryColumn: _propTypes.default.object,
259
+ result: _propTypes.default.array,
260
+ tables: _propTypes.default.array,
261
+ globalTheme: _propTypes.default.string,
262
+ chartColorTheme: _propTypes.default.string,
263
+ toggleRecords: _propTypes.default.func,
264
+ customRender: _propTypes.default.func
265
+ };
266
+ var _default = exports.default = MapBubble;
@@ -0,0 +1,279 @@
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 _colorRules = require("../../constants/color-rules");
18
+ var _context = _interopRequireDefault(require("../../context"));
19
+ var _mapJson = _interopRequireDefault(require("../../services/map-json"));
20
+ var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
21
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
22
+ class Map extends _chartComponent.default {
23
+ constructor(props) {
24
+ super(props);
25
+ this.handleResize = () => {
26
+ this.chart.node() && this.chart.node().remove();
27
+ this.createChart();
28
+ this.drawChart();
29
+ };
30
+ this.createChart = () => {
31
+ const {
32
+ chart
33
+ } = this.props;
34
+ const initConfig = {
35
+ insertPadding: 30
36
+ };
37
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
38
+ };
39
+ this.drawChart = async () => {
40
+ let {
41
+ result: data,
42
+ chart
43
+ } = this.props;
44
+ if (!Array.isArray(data)) return;
45
+ const {
46
+ type
47
+ } = chart.config;
48
+ const mediaUrl = _context.default.getSetting('mediaUrl');
49
+ const mapJson = await (0, _mapJson.default)(_constants.MAP_LEVEL.WORLD, '', mediaUrl);
50
+ if (!mapJson) return;
51
+ const newMapJson = (0, _topojson.feature)(mapJson, mapJson.objects);
52
+ const statisticNewData = this.formatWorldMapStatisticData(data, newMapJson, type);
53
+ this.draw(statisticNewData, newMapJson);
54
+ };
55
+ this.showTooltip = (event, data) => {
56
+ const curData = data.find(item => item.name.includes(event.target.parentNode.getAttribute('data-name')));
57
+ const title = curData.nameType === 'en' ? curData.name : curData.name_cn;
58
+ const value = Number(event.target.parentNode.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
+ isCalculateByView
104
+ } = this.props;
105
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
106
+ const {
107
+ data_color,
108
+ legend_size,
109
+ legend_direction,
110
+ summary_method
111
+ } = chart.config;
112
+ const {
113
+ width: chartWidth,
114
+ height: chartHeight,
115
+ insertPadding
116
+ } = this.chartBoundingClientRect;
117
+ const currentColorOption = _colorRules.COLOR_OPTIONS.filter(item => item.name === data_color)[0] || _colorRules.COLOR_OPTIONS[0];
118
+ const {
119
+ exampleColors,
120
+ highlightedBorderColor
121
+ } = currentColorOption;
122
+
123
+ // Color scale
124
+ const minVal = d3.min(data, d => d.value);
125
+ const maxVal = d3.max(data, d => d.value);
126
+ const color = d3.scaleSequential([minVal, maxVal], d3.interpolateRgbBasis(exampleColors)).unknown('#e2e2e2');
127
+
128
+ // 1. Setting up projection
129
+ const projection = d3.geoMercator().fitExtent([[insertPadding, insertPadding], [chartWidth - insertPadding, chartHeight - insertPadding]], mapJson);
130
+
131
+ // 2. Generate a path based on projection
132
+ const pathGenerator = d3.geoPath(projection);
133
+
134
+ // 3. Rendering map
135
+ this.chart.append('g').attr('class', 'map-wrapper').on('click', event => {
136
+ if (isCalculateByView) {
137
+ const value = Number(event.target.parentNode.getAttribute('data-value'));
138
+ if (value) {
139
+ const name = event.target.parentNode.getAttribute('data-name');
140
+ const newData = data.find(item => item.name.includes(name));
141
+ newData && this.props.toggleRecords([newData]);
142
+ }
143
+ }
144
+ }).on('mousemove', event => {
145
+ console.log(data);
146
+ const value = Number(event.target.parentNode.getAttribute('data-value'));
147
+ if (this.curElement) {
148
+ this.handleAcitveAndInActiveState('inActive', event, highlightedBorderColor);
149
+ this.curElement = null;
150
+ }
151
+ if (value) {
152
+ this.curElement = event.target.parentNode;
153
+ this.showTooltip(event, data);
154
+ this.handleAcitveAndInActiveState('active', event, highlightedBorderColor);
155
+ } else {
156
+ this.hiddenTooltip(event);
157
+ }
158
+ }).on('mouseleave', event => {
159
+ if (this.curElement) {
160
+ this.hiddenTooltip(event);
161
+ this.handleAcitveAndInActiveState('inActive', event, highlightedBorderColor);
162
+ this.curElement = null;
163
+ }
164
+ }).selectAll().data(mapJson.features).join('g').attr('data-name', d => d.properties.name).attr('stroke-width', 1).attr('stroke', '#bdbdbd').attr('stroke-opacity', 1).attr('opacity', 1).append('path').attr('d', d => {
165
+ return pathGenerator(d);
166
+ }).attr('data-name', d => d.properties.name).call(g => {
167
+ var _g$nodes$find;
168
+ const chinaGroup = (_g$nodes$find = g.nodes().find(item => item.getAttribute('data-name').includes('China'))) === null || _g$nodes$find === void 0 ? void 0 : _g$nodes$find.parentNode;
169
+ const chinaTaiwan = g.nodes().find(item => item.getAttribute('data-name').includes('Taiwan'));
170
+ if (chinaGroup) {
171
+ (chinaTaiwan === null || chinaTaiwan === void 0 ? void 0 : chinaTaiwan.parentNode) && chinaTaiwan.parentNode.remove();
172
+ chinaGroup.append(chinaTaiwan);
173
+ }
174
+ }).call(g => {
175
+ g.nodes().forEach(item => {
176
+ const curGroup = item.parentNode;
177
+ const curName = curGroup.getAttribute('data-name');
178
+ const curItemData = data.find(d => d.name.includes(curName));
179
+ if (curItemData) {
180
+ d3.select(curGroup).attr('fill', color(curItemData.value));
181
+ d3.select(curGroup).attr('data-value', curItemData.value);
182
+ } else {
183
+ d3.select(curGroup).attr('fill', color());
184
+ }
185
+ });
186
+ });
187
+ const columnData = this.getColumnData();
188
+ this.setContinuousLegend({
189
+ previewType: canvasStyle.previewType,
190
+ theme,
191
+ colorRange: exampleColors,
192
+ legendDirection: legend_direction,
193
+ legendSize: legend_size,
194
+ legendTextRange: [_utils.BaseUtils.getSummaryValueDisplayString(columnData, minVal, summary_method), _utils.BaseUtils.getSummaryValueDisplayString(columnData, maxVal, summary_method)]
195
+ });
196
+ };
197
+ this.handleAcitveAndInActiveState = (state, event, highlightedBorderColor) => {
198
+ if (state === 'active') {
199
+ const lastElement = Array.from(event.target.parentNode.parentNode.children).at(-1);
200
+
201
+ // Add element to the end
202
+ d3.select(this.curElement).transition().duration(this.transitionDuration).attr('stroke-opacity', 0.7).attr('stroke-width', 0.5).attr('stroke', highlightedBorderColor);
203
+ lastElement.after(this.curElement);
204
+ return;
205
+ }
206
+ if (this.curElement) {
207
+ d3.select(this.curElement).transition().duration(this.transitionDuration).attr('stroke-opacity', 1).attr('stroke-width', 1).attr('stroke', '#bdbdbd');
208
+ }
209
+ };
210
+ this.getColumnData = () => {
211
+ const {
212
+ chart
213
+ } = this.props;
214
+ const {
215
+ summary_type,
216
+ summary_column_key,
217
+ table_id
218
+ } = chart.config;
219
+ let columnData = _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
220
+ if (summary_type === _constants.CHART_SUMMARY_TYPE.ADVANCED) {
221
+ const table = (0, _dtableUtils.getTableById)(table_id);
222
+ const summaryColumn = (0, _dtableUtils.getTableColumnByKey)(table, summary_column_key) || {};
223
+ columnData = summaryColumn.data || _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
224
+ }
225
+ return columnData;
226
+ };
227
+ this.chart = null;
228
+ this.state = {
229
+ tooltipData: null,
230
+ toolTipPosition: null
231
+ };
232
+ this.curElement = null; // Regions that currently contain data
233
+ }
234
+ componentDidMount() {
235
+ this.createChart();
236
+ this.drawChart();
237
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
238
+ window.addEventListener('resize', this.debouncedHandleResize);
239
+ }
240
+ componentDidUpdate(prevProps) {
241
+ super.componentDidUpdate(prevProps);
242
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
243
+ this.createChart();
244
+ this.drawChart();
245
+ }
246
+ }
247
+ componentWillUnmount() {
248
+ this.chart.node() && this.chart.node().remove();
249
+ window.removeEventListener('resize', this.debouncedHandleResize);
250
+ }
251
+ render() {
252
+ const {
253
+ tooltipData,
254
+ toolTipPosition
255
+ } = this.state;
256
+ return /*#__PURE__*/_react.default.createElement("div", {
257
+ ref: ref => this.container = ref,
258
+ className: "sea-chart-container"
259
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
260
+ tooltipData: tooltipData,
261
+ toolTipPosition: toolTipPosition,
262
+ chart: this.chart
263
+ }));
264
+ }
265
+ }
266
+ Map.propTypes = {
267
+ canvasStyle: _propTypes.default.object,
268
+ chart: _propTypes.default.object,
269
+ groupbyColumn: _propTypes.default.object,
270
+ columnGroupbyColumn: _propTypes.default.object,
271
+ summaryColumn: _propTypes.default.object,
272
+ result: _propTypes.default.array,
273
+ tables: _propTypes.default.array,
274
+ globalTheme: _propTypes.default.string,
275
+ chartColorTheme: _propTypes.default.string,
276
+ toggleRecords: _propTypes.default.func,
277
+ customRender: _propTypes.default.func
278
+ };
279
+ var _default = exports.default = Map;
@@ -50,8 +50,9 @@ class Map extends _chartComponent.default {
50
50
  const mediaUrl = _context.default.getSetting('mediaUrl');
51
51
  const mapJson = await (0, _mapJson.default)(map_level, map_location, mediaUrl);
52
52
  if (!mapJson) return;
53
- const statisticNewData = this.formatMapStatisticData(data, mapJson, type);
54
- this.draw(statisticNewData, mapJson);
53
+ const newMapJson = map_level === _constants.MAP_LEVEL.COUNTRY ? (0, _topojson.feature)(mapJson, mapJson.objects) : mapJson;
54
+ const statisticNewData = this.formatMapStatisticData(data, newMapJson, type);
55
+ this.draw(statisticNewData, newMapJson);
55
56
  };
56
57
  this.showTooltip = event => {
57
58
  const title = event.target.getAttribute('data-name');
@@ -103,7 +104,6 @@ class Map extends _chartComponent.default {
103
104
  } = this.props;
104
105
  const theme = _constants.CHART_THEME_COLOR[globalTheme];
105
106
  const {
106
- map_level = _constants.MAP_LEVEL.COUNTRY,
107
107
  data_color,
108
108
  legend_size,
109
109
  legend_direction,
@@ -114,7 +114,6 @@ class Map extends _chartComponent.default {
114
114
  height: chartHeight,
115
115
  insertPadding
116
116
  } = this.chartBoundingClientRect;
117
- const newMapData = map_level === _constants.MAP_LEVEL.COUNTRY ? (0, _topojson.feature)(mapJson, mapJson.objects) : mapJson;
118
117
  const currentColorOption = _colorRules.COLOR_OPTIONS.filter(item => item.name === data_color)[0] || _colorRules.COLOR_OPTIONS[0];
119
118
  const {
120
119
  exampleColors,
@@ -127,7 +126,7 @@ class Map extends _chartComponent.default {
127
126
  const color = d3.scaleSequential([minVal, maxVal], d3.interpolateRgbBasis(exampleColors)).unknown('#e2e2e2');
128
127
 
129
128
  // 1. Setting up projection
130
- const projection = d3.geoMercator().fitSize([chartWidth - insertPadding, chartHeight - insertPadding], newMapData);
129
+ const projection = d3.geoMercator().fitExtent([[insertPadding, insertPadding], [chartWidth - insertPadding, chartHeight - insertPadding]], mapJson);
131
130
 
132
131
  // 2. Generate a path based on projection
133
132
  const pathGenerator = d3.geoPath(projection);
@@ -159,7 +158,7 @@ class Map extends _chartComponent.default {
159
158
  this.handleAcitveAndInActiveState('inActive', event, highlightedBorderColor);
160
159
  this.curElement = null;
161
160
  }
162
- }).selectAll().data(newMapData.features).join('g').append('path').attr('d', d => {
161
+ }).selectAll().data(mapJson.features).join('g').append('path').attr('d', d => {
163
162
  return pathGenerator(d);
164
163
  }).attr('stroke-width', 1).attr('stroke', '#bdbdbd').attr('stroke-opacity', 1).attr('opacity', 1).attr('data-name', d => d.properties.name).call(g => {
165
164
  g.nodes().forEach(item => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sea-chart",
3
- "version": "2.0.26",
3
+ "version": "2.0.28",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@dnd-kit/core": "^6.1.0",