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.
@@ -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().fitSize([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().fitSize([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;