sea-chart 2.0.14 → 2.0.16
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/components/tooltip/index.js +1 -1
- package/dist/components/types-dialog/index.js +1 -1
- package/dist/view/wrapper/area-group.js +423 -0
- package/dist/view/wrapper/area.js +400 -0
- package/dist/view/wrapper/chart-component.js +145 -54
- package/dist/view/wrapper/index.js +42 -0
- package/dist/view/wrapper/line-group.js +403 -0
- package/dist/view/wrapper/line.js +371 -0
- package/dist/view/wrapper/pie.js +275 -0
- package/dist/view/wrapper/ring.js +328 -0
- package/package.json +1 -1
|
@@ -0,0 +1,400 @@
|
|
|
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 _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
+
var _react = _interopRequireDefault(require("react"));
|
|
11
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
12
|
+
var _lodashEs = require("lodash-es");
|
|
13
|
+
var d3 = _interopRequireWildcard(require("d3"));
|
|
14
|
+
var _constants = require("../../constants");
|
|
15
|
+
var _intl = _interopRequireDefault(require("../../intl"));
|
|
16
|
+
var _utils = require("../../utils");
|
|
17
|
+
var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
|
|
18
|
+
var _chartComponent = _interopRequireDefault(require("./chart-component"));
|
|
19
|
+
class Area extends _chartComponent.default {
|
|
20
|
+
constructor(props) {
|
|
21
|
+
super(props);
|
|
22
|
+
this.handleResize = () => {
|
|
23
|
+
this.chart.node() && this.chart.node().remove();
|
|
24
|
+
this.createChart();
|
|
25
|
+
this.drawChart();
|
|
26
|
+
};
|
|
27
|
+
this.createChart = () => {
|
|
28
|
+
const {
|
|
29
|
+
chart
|
|
30
|
+
} = this.props;
|
|
31
|
+
const {
|
|
32
|
+
y_axis_show_label,
|
|
33
|
+
x_axis_show_label,
|
|
34
|
+
y_axis_show_value
|
|
35
|
+
} = chart.config;
|
|
36
|
+
const initConfig = {
|
|
37
|
+
insertPadding: 30,
|
|
38
|
+
marginLeft: y_axis_show_label ? 20 : 0,
|
|
39
|
+
marginBottom: x_axis_show_label ? 20 : 0,
|
|
40
|
+
marginTop: y_axis_show_value ? 15 : 0
|
|
41
|
+
};
|
|
42
|
+
this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
|
|
43
|
+
};
|
|
44
|
+
this.drawChart = () => {
|
|
45
|
+
let {
|
|
46
|
+
result: data,
|
|
47
|
+
customRender
|
|
48
|
+
} = this.props;
|
|
49
|
+
data = _utils.BaseUtils.formatEmptyName(data, '', _intl.default.get('Empty'));
|
|
50
|
+
if (!Array.isArray(data)) return;
|
|
51
|
+
this.draw(data);
|
|
52
|
+
(0, _utils.isFunction)(customRender) && customRender(this.chart);
|
|
53
|
+
this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
|
|
54
|
+
};
|
|
55
|
+
this.draw = data => {
|
|
56
|
+
const {
|
|
57
|
+
chart,
|
|
58
|
+
globalTheme,
|
|
59
|
+
tables
|
|
60
|
+
} = this.props;
|
|
61
|
+
const theme = _constants.CHART_THEME_COLOR[globalTheme];
|
|
62
|
+
const {
|
|
63
|
+
display_goal_line,
|
|
64
|
+
goal_label,
|
|
65
|
+
goal_value
|
|
66
|
+
} = chart.style_config || {};
|
|
67
|
+
const {
|
|
68
|
+
y_axis_summary_type,
|
|
69
|
+
y_axis_column_key,
|
|
70
|
+
y_axis_summary_column_key,
|
|
71
|
+
line_type,
|
|
72
|
+
y_axis_show_value,
|
|
73
|
+
label_font_size,
|
|
74
|
+
table_id,
|
|
75
|
+
y_axis_auto_range,
|
|
76
|
+
y_axis_min,
|
|
77
|
+
y_axis_max
|
|
78
|
+
} = chart.config;
|
|
79
|
+
const {
|
|
80
|
+
width: chartWidth,
|
|
81
|
+
height: chartHeight,
|
|
82
|
+
insertPadding,
|
|
83
|
+
marginTop
|
|
84
|
+
} = this.chartBoundingClientRect;
|
|
85
|
+
const tooltipTitle = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
|
|
86
|
+
|
|
87
|
+
// Y axis
|
|
88
|
+
const niceEnd = d3.nice(0, d3.max(data, d => d.value), 5)[1];
|
|
89
|
+
const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, niceEnd] : [y_axis_min || 0, y_axis_max || niceEnd]).range([chartHeight - insertPadding, insertPadding + marginTop]);
|
|
90
|
+
this.chart.append('g').attr('transform', "translate(".concat(insertPadding, ", 0)")).call(d3.axisLeft(y).tickSizeInner(0).ticks(5).tickFormat(d => d)).call(g => this.drawYaxis(g, theme));
|
|
91
|
+
|
|
92
|
+
// X axis
|
|
93
|
+
const xDomain = data.map(item => item.name);
|
|
94
|
+
const x = d3.scaleBand().domain(xDomain).range([insertPadding + this.horizontalOverflowOffset, chartWidth - insertPadding]).paddingInner(0.4).paddingOuter(0.1);
|
|
95
|
+
this.ticksWrapper = this.chart.append('g').attr('transform', "translate(0, ".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(x).tickSizeOuter(0).tickSizeInner(5)).call(g => {
|
|
96
|
+
this.ticksAddName(g);
|
|
97
|
+
g.selectAll('.domain').attr('stroke', theme.XAxisColor);
|
|
98
|
+
g.selectAll('.tick line').attr('stroke', theme.XAxisColor);
|
|
99
|
+
g.selectAll('text').attr('font-size', theme.fontSize);
|
|
100
|
+
g.selectAll('text').attr('fill', theme.textColor);
|
|
101
|
+
this.checkTickOverlap(g);
|
|
102
|
+
});
|
|
103
|
+
const rectsWrapper = this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id));
|
|
104
|
+
|
|
105
|
+
// Line
|
|
106
|
+
const circleData = xDomain.map(() => ({}));
|
|
107
|
+
const line = d3.line().x((d, index) => {
|
|
108
|
+
const xVal = x(d.name) + x.bandwidth() / 2;
|
|
109
|
+
circleData[index]['x'] = xVal;
|
|
110
|
+
circleData[index]['name'] = d.name;
|
|
111
|
+
return xVal;
|
|
112
|
+
}).y((d, index) => {
|
|
113
|
+
const yVal = y(d.value);
|
|
114
|
+
circleData[index]['y'] = yVal;
|
|
115
|
+
circleData[index]['value'] = d.value;
|
|
116
|
+
return yVal;
|
|
117
|
+
}).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
|
|
118
|
+
this.Line = rectsWrapper.append('path').attr('fill', 'none').attr('stroke', this.getAreaColor()).attr('stroke-width', 2).attr('d', () => line(data));
|
|
119
|
+
|
|
120
|
+
// Area
|
|
121
|
+
const area = d3.area().x(d => {
|
|
122
|
+
const xVal = x(d.name) + x.bandwidth() / 2;
|
|
123
|
+
return xVal;
|
|
124
|
+
}).y0(y(0)).y1(d => y(d.value)).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
|
|
125
|
+
this.Area = rectsWrapper.append('path').attr('fill', this.getAreaColor()).attr('d', () => area(data)).attr('opacity', '0.3');
|
|
126
|
+
|
|
127
|
+
// circle
|
|
128
|
+
circleData.forEach(item => {
|
|
129
|
+
rectsWrapper.append('circle').attr('cx', item.x).attr('cy', item.y).attr('r', 3).attr('fill', this.getAreaColor()).attr('opacity', y_axis_show_value ? 1 : 0).attr('data-text', item.value).attr('data-name', item.name).call(g => {
|
|
130
|
+
// circle label
|
|
131
|
+
if (y_axis_show_value) {
|
|
132
|
+
const curCircleEl = g.node();
|
|
133
|
+
rectsWrapper.append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(curCircleEl.getAttribute('data-text')).call(g => {
|
|
134
|
+
const {
|
|
135
|
+
width
|
|
136
|
+
} = g.node().getBoundingClientRect();
|
|
137
|
+
const translateX = Number(curCircleEl.getAttribute('cx')) - width / 2;
|
|
138
|
+
const translateY = Number(curCircleEl.getAttribute('cy')) - 10;
|
|
139
|
+
g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}).on('click', (event, data) => {
|
|
143
|
+
this.props.toggleRecords(data);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
this.chart.on('mouseover', event => {
|
|
147
|
+
this.updateCircleAndTickStyle({
|
|
148
|
+
event,
|
|
149
|
+
state: 'zoomIn',
|
|
150
|
+
circleData,
|
|
151
|
+
rectsWrapper,
|
|
152
|
+
eventState: 'over',
|
|
153
|
+
tooltipTitle
|
|
154
|
+
});
|
|
155
|
+
}).on('mousemove', event => {
|
|
156
|
+
this.updateCircleAndTickStyle({
|
|
157
|
+
event,
|
|
158
|
+
state: 'zoomIn',
|
|
159
|
+
circleData,
|
|
160
|
+
rectsWrapper,
|
|
161
|
+
eventState: 'move',
|
|
162
|
+
tooltipTitle
|
|
163
|
+
});
|
|
164
|
+
}).on('mouseleave', event => {
|
|
165
|
+
this.updateCircleAndTickStyle({
|
|
166
|
+
event,
|
|
167
|
+
state: 'zoomOut',
|
|
168
|
+
circleData,
|
|
169
|
+
rectsWrapper,
|
|
170
|
+
eventState: 'leave',
|
|
171
|
+
tooltipTitle
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
if (display_goal_line && goal_label && goal_value) {
|
|
175
|
+
this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
this.updateCircleAndTickStyle = _ref => {
|
|
179
|
+
var _rectsWrapper$selectA, _this$ticksWrapper$se;
|
|
180
|
+
let {
|
|
181
|
+
event,
|
|
182
|
+
state,
|
|
183
|
+
circleData,
|
|
184
|
+
rectsWrapper,
|
|
185
|
+
eventState,
|
|
186
|
+
tooltipTitle
|
|
187
|
+
} = _ref;
|
|
188
|
+
const {
|
|
189
|
+
y_axis_show_value
|
|
190
|
+
} = this.props.chart.config;
|
|
191
|
+
const {
|
|
192
|
+
height: chartHeight,
|
|
193
|
+
insertPadding,
|
|
194
|
+
marginTop
|
|
195
|
+
} = this.chartBoundingClientRect;
|
|
196
|
+
const {
|
|
197
|
+
offsetX
|
|
198
|
+
} = event;
|
|
199
|
+
const minDistanceItem = this.getMinDistanceItem(offsetX, circleData);
|
|
200
|
+
const circleList = (_rectsWrapper$selectA = rectsWrapper.selectAll('circle')) === null || _rectsWrapper$selectA === void 0 ? void 0 : _rectsWrapper$selectA.nodes();
|
|
201
|
+
if (circleList.length !== 0) {
|
|
202
|
+
if (state === 'zoomIn') {
|
|
203
|
+
circleList.forEach(circle => {
|
|
204
|
+
const name = circle.getAttribute('data-name');
|
|
205
|
+
if (name === minDistanceItem.name) {
|
|
206
|
+
d3.select(circle).attr('opacity', 1);
|
|
207
|
+
d3.select(circle).attr('r', 5);
|
|
208
|
+
} else {
|
|
209
|
+
d3.select(circle).attr('opacity', 0.3);
|
|
210
|
+
d3.select(circle).attr('r', 3);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
this.Area.attr('opacity', 0.1);
|
|
214
|
+
this.Line.attr('opacity', 0.3);
|
|
215
|
+
} else {
|
|
216
|
+
circleList.forEach(circle => {
|
|
217
|
+
if (!y_axis_show_value) {
|
|
218
|
+
d3.select(circle).attr('opacity', 0);
|
|
219
|
+
} else {
|
|
220
|
+
d3.select(circle).attr('opacity', 1);
|
|
221
|
+
}
|
|
222
|
+
d3.select(circle).attr('r', 3);
|
|
223
|
+
});
|
|
224
|
+
this.Area.attr('opacity', 0.3);
|
|
225
|
+
this.Line.attr('opacity', 1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const ticks = (_this$ticksWrapper$se = this.ticksWrapper.selectAll('.tick line')) === null || _this$ticksWrapper$se === void 0 ? void 0 : _this$ticksWrapper$se.nodes();
|
|
229
|
+
if (ticks.length !== 0) {
|
|
230
|
+
if (state === 'zoomIn') {
|
|
231
|
+
ticks.forEach(tick => {
|
|
232
|
+
const name = tick.getAttribute('data-name');
|
|
233
|
+
if (name === minDistanceItem.name) {
|
|
234
|
+
d3.select(tick).attr('y2', -(chartHeight - insertPadding * 2 - marginTop));
|
|
235
|
+
} else {
|
|
236
|
+
d3.select(tick).attr('y2', 0);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
} else {
|
|
240
|
+
ticks.forEach(tick => {
|
|
241
|
+
d3.select(tick).attr('y2', 0);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// tooltip
|
|
247
|
+
if (eventState === 'over') {
|
|
248
|
+
this.showTooltip(event, minDistanceItem, tooltipTitle);
|
|
249
|
+
}
|
|
250
|
+
if (eventState === 'move') {
|
|
251
|
+
this.moveTooltip(event, minDistanceItem, tooltipTitle);
|
|
252
|
+
}
|
|
253
|
+
if (eventState === 'leave') {
|
|
254
|
+
this.hiddenTooltip();
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
this.showTooltip = (event, data, title) => {
|
|
258
|
+
const {
|
|
259
|
+
offsetX,
|
|
260
|
+
offsetY
|
|
261
|
+
} = event;
|
|
262
|
+
const {
|
|
263
|
+
chart,
|
|
264
|
+
summaryColumn
|
|
265
|
+
} = this.props;
|
|
266
|
+
const {
|
|
267
|
+
y_axis_summary_method
|
|
268
|
+
} = chart.config;
|
|
269
|
+
const newTooltipData = {
|
|
270
|
+
title: title,
|
|
271
|
+
items: [{
|
|
272
|
+
color: this.getAreaColor(),
|
|
273
|
+
name: data.name,
|
|
274
|
+
value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, data.value, y_axis_summary_method)
|
|
275
|
+
}]
|
|
276
|
+
};
|
|
277
|
+
this.setState({
|
|
278
|
+
tooltipData: newTooltipData
|
|
279
|
+
});
|
|
280
|
+
this.setState({
|
|
281
|
+
toolTipPosition: {
|
|
282
|
+
offsetX,
|
|
283
|
+
offsetY
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
this.moveTooltip = (event, data, title) => {
|
|
288
|
+
const {
|
|
289
|
+
offsetX,
|
|
290
|
+
offsetY
|
|
291
|
+
} = event;
|
|
292
|
+
const {
|
|
293
|
+
chart,
|
|
294
|
+
summaryColumn
|
|
295
|
+
} = this.props;
|
|
296
|
+
const {
|
|
297
|
+
y_axis_summary_method
|
|
298
|
+
} = chart.config;
|
|
299
|
+
const newTooltipData = {
|
|
300
|
+
title: title,
|
|
301
|
+
items: [{
|
|
302
|
+
color: this.getAreaColor(),
|
|
303
|
+
name: data.name,
|
|
304
|
+
value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, data.value, y_axis_summary_method)
|
|
305
|
+
}]
|
|
306
|
+
};
|
|
307
|
+
this.setState({
|
|
308
|
+
tooltipData: newTooltipData
|
|
309
|
+
});
|
|
310
|
+
this.setState({
|
|
311
|
+
toolTipPosition: {
|
|
312
|
+
offsetX,
|
|
313
|
+
offsetY
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
this.hiddenTooltip = event => {
|
|
318
|
+
this.setState({
|
|
319
|
+
toolTipPosition: null
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
this.getAreaColor = () => {
|
|
323
|
+
const {
|
|
324
|
+
chart,
|
|
325
|
+
chartColorTheme
|
|
326
|
+
} = this.props;
|
|
327
|
+
const {
|
|
328
|
+
y_axis_label_color,
|
|
329
|
+
color_option
|
|
330
|
+
} = chart.config;
|
|
331
|
+
let chartBarColor = _constants.CHART_STYLE_COLORS[0];
|
|
332
|
+
if (chartColorTheme) {
|
|
333
|
+
chartBarColor = _utils.BaseUtils.getCurrentTheme(chartColorTheme).colors[0];
|
|
334
|
+
}
|
|
335
|
+
if (color_option === _constants.TYPE_COLOR_USING.USE_SPECIFIC_COLORS && y_axis_label_color) {
|
|
336
|
+
chartBarColor = y_axis_label_color;
|
|
337
|
+
}
|
|
338
|
+
return chartBarColor;
|
|
339
|
+
};
|
|
340
|
+
this.chart = null;
|
|
341
|
+
this.state = {
|
|
342
|
+
tooltipData: null,
|
|
343
|
+
toolTipPosition: null
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
componentDidMount() {
|
|
347
|
+
this.createChart();
|
|
348
|
+
this.drawChart();
|
|
349
|
+
this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
|
|
350
|
+
window.addEventListener('resize', this.debouncedHandleResize);
|
|
351
|
+
super.componentDidMount();
|
|
352
|
+
}
|
|
353
|
+
componentDidUpdate(prevProps) {
|
|
354
|
+
super.componentDidUpdate(prevProps);
|
|
355
|
+
if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
|
|
356
|
+
this.chart.node() && this.chart.node().remove();
|
|
357
|
+
this.createChart();
|
|
358
|
+
this.drawChart();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
componentWillUnmount() {
|
|
362
|
+
this.chart.node() && this.chart.node().remove();
|
|
363
|
+
window.removeEventListener('resize', this.debouncedHandleResize);
|
|
364
|
+
super.componentWillUnmount();
|
|
365
|
+
}
|
|
366
|
+
render() {
|
|
367
|
+
const {
|
|
368
|
+
chart
|
|
369
|
+
} = this.props;
|
|
370
|
+
const {
|
|
371
|
+
tooltipData,
|
|
372
|
+
toolTipPosition
|
|
373
|
+
} = this.state;
|
|
374
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
375
|
+
ref: ref => this.container = ref,
|
|
376
|
+
className: (0, _classnames.default)('sea-chart-container', {
|
|
377
|
+
'show-x-axis-label': this.isShowXAxisLabel(chart),
|
|
378
|
+
'show-y-axis-label': this.isShowYAxisLabel(chart)
|
|
379
|
+
})
|
|
380
|
+
}, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
|
|
381
|
+
tooltipData: tooltipData,
|
|
382
|
+
toolTipPosition: toolTipPosition,
|
|
383
|
+
chart: this.chart
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
Area.propTypes = {
|
|
388
|
+
canvasStyle: _propTypes.default.object,
|
|
389
|
+
chart: _propTypes.default.object,
|
|
390
|
+
groupbyColumn: _propTypes.default.object,
|
|
391
|
+
columnGroupbyColumn: _propTypes.default.object,
|
|
392
|
+
summaryColumn: _propTypes.default.object,
|
|
393
|
+
result: _propTypes.default.array,
|
|
394
|
+
tables: _propTypes.default.array,
|
|
395
|
+
globalTheme: _propTypes.default.string,
|
|
396
|
+
chartColorTheme: _propTypes.default.string,
|
|
397
|
+
toggleRecords: _propTypes.default.func,
|
|
398
|
+
customRender: _propTypes.default.func
|
|
399
|
+
};
|
|
400
|
+
var _default = exports.default = Area;
|
|
@@ -595,6 +595,7 @@ class ChartComponent extends _react.Component {
|
|
|
595
595
|
groupColumn
|
|
596
596
|
} = _ref;
|
|
597
597
|
if (!this.chart) return;
|
|
598
|
+
data.forEach(item => item[legendName] = String(item[legendName]));
|
|
598
599
|
const legendData = (0, _lodashEs.cloneDeep)(data);
|
|
599
600
|
this.legendConfig = {
|
|
600
601
|
legendRectWidth: 20,
|
|
@@ -604,6 +605,7 @@ class ChartComponent extends _react.Component {
|
|
|
604
605
|
legendItemMargin: 20,
|
|
605
606
|
legendRecTextGap: 8,
|
|
606
607
|
legendPageNavWrapperWidth: 100,
|
|
608
|
+
legendPageNavWrapperHeight: 18,
|
|
607
609
|
legendPosition,
|
|
608
610
|
legendName,
|
|
609
611
|
theme
|
|
@@ -615,7 +617,8 @@ class ChartComponent extends _react.Component {
|
|
|
615
617
|
}
|
|
616
618
|
const {
|
|
617
619
|
width: chartWidth,
|
|
618
|
-
insertPadding
|
|
620
|
+
insertPadding,
|
|
621
|
+
rightLegendSpace
|
|
619
622
|
} = this.chartBoundingClientRect;
|
|
620
623
|
const groupsData = this.getLegendDataGroups(legendData);
|
|
621
624
|
const legendWrapper = this.chart.append('g').attr('class', "legend-wrapper-".concat((_this$chart$node = this.chart.node()) === null || _this$chart$node === void 0 ? void 0 : _this$chart$node.id));
|
|
@@ -631,7 +634,8 @@ class ChartComponent extends _react.Component {
|
|
|
631
634
|
// Render Page navigator
|
|
632
635
|
if (groupsData.length > 1) {
|
|
633
636
|
const {
|
|
634
|
-
legendPageNavWrapperWidth
|
|
637
|
+
legendPageNavWrapperWidth,
|
|
638
|
+
legendItemMargin
|
|
635
639
|
} = this.legendConfig;
|
|
636
640
|
let curCount = 0;
|
|
637
641
|
const pageNavigator = legendWrapper.append('g').attr('class', 'legend-flip-page');
|
|
@@ -670,6 +674,7 @@ class ChartComponent extends _react.Component {
|
|
|
670
674
|
// update pageNavigator transform
|
|
671
675
|
pageNavigator.call(g => {
|
|
672
676
|
let groupTranslateX = 0;
|
|
677
|
+
let groupTranslateY = 0;
|
|
673
678
|
if (legendPosition === 'top-right') {
|
|
674
679
|
groupTranslateX = insertPadding;
|
|
675
680
|
} else if (legendPosition === 'top-left') {
|
|
@@ -679,8 +684,14 @@ class ChartComponent extends _react.Component {
|
|
|
679
684
|
} = g.node().getBoundingClientRect();
|
|
680
685
|
const offset = legendPageNavWrapperWidth - width;
|
|
681
686
|
groupTranslateX = groupTranslateX + offset;
|
|
687
|
+
} else if (legendPosition === 'center-right') {
|
|
688
|
+
groupTranslateX = chartWidth - insertPadding - rightLegendSpace;
|
|
689
|
+
const {
|
|
690
|
+
height
|
|
691
|
+
} = g.node().parentNode.getBoundingClientRect();
|
|
692
|
+
groupTranslateY = groupTranslateY + height + legendItemMargin;
|
|
682
693
|
}
|
|
683
|
-
g.attr('transform', "translate(".concat(groupTranslateX, ",
|
|
694
|
+
g.attr('transform', "translate(".concat(groupTranslateX, ", ").concat(groupTranslateY, ")"));
|
|
684
695
|
});
|
|
685
696
|
}
|
|
686
697
|
};
|
|
@@ -732,35 +743,53 @@ class ChartComponent extends _react.Component {
|
|
|
732
743
|
const parentNode = rect.parentNode;
|
|
733
744
|
d3.select(parentNode).append('text').attr('x', legendRectWidth + legendRecTextGap).attr('fill', theme.legendTextColor).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(rect.dataset.text)).attr('data-text', rect.dataset.text).attr('dominant-baseline', 'hanging');
|
|
734
745
|
});
|
|
735
|
-
// update g translateX
|
|
736
746
|
const legendItems = Array.from(legendWrapper.node().children).filter(item => item.getAttribute('class') !== 'legend-flip-page');
|
|
737
747
|
const {
|
|
738
748
|
start,
|
|
739
|
-
end
|
|
749
|
+
end,
|
|
750
|
+
top,
|
|
751
|
+
bottom
|
|
740
752
|
} = this.getLegendBoundary(legendPosition);
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
753
|
+
if (top && bottom) {
|
|
754
|
+
// update g translateY
|
|
755
|
+
legendItems.forEach((item, index) => {
|
|
756
|
+
let translateY = top;
|
|
757
|
+
const prevItem = legendItems[index - 1];
|
|
758
|
+
if (index > 0) {
|
|
759
|
+
const {
|
|
760
|
+
height
|
|
761
|
+
} = prevItem.getBoundingClientRect();
|
|
762
|
+
const prevTranslateY = Number(prevItem.getAttribute('data-translateY'));
|
|
763
|
+
translateY = prevTranslateY + height + legendItemMargin;
|
|
764
|
+
}
|
|
765
|
+
d3.select(item).attr('transform', "translate(".concat(start, ",").concat(translateY, ")")).attr('data-translateY', translateY);
|
|
766
|
+
});
|
|
767
|
+
} else {
|
|
768
|
+
// update g translateX
|
|
769
|
+
legendItems.forEach((item, index) => {
|
|
770
|
+
let translateX = start;
|
|
771
|
+
const prevItem = legendItems[index - 1];
|
|
772
|
+
if (index > 0) {
|
|
773
|
+
const {
|
|
774
|
+
width
|
|
775
|
+
} = prevItem.getBoundingClientRect();
|
|
776
|
+
const prevTranslateX = Number(prevItem.getAttribute('data-translateX'));
|
|
777
|
+
translateX = prevTranslateX + width + legendItemMargin;
|
|
778
|
+
}
|
|
779
|
+
d3.select(item).attr('transform', "translate(".concat(translateX, ",0)")).attr('data-translateX', translateX);
|
|
752
780
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
781
|
+
// legend items add offset
|
|
782
|
+
if (legendPosition === 'top-right') {
|
|
783
|
+
d3.select(item).attr('opacity', 0);
|
|
784
|
+
// Execute only once
|
|
785
|
+
if (index === legendItems.length - 1) {
|
|
786
|
+
queueMicrotask(() => {
|
|
787
|
+
this.setLegendItemOffset(legendItems, end);
|
|
788
|
+
});
|
|
789
|
+
}
|
|
761
790
|
}
|
|
762
|
-
}
|
|
763
|
-
}
|
|
791
|
+
});
|
|
792
|
+
}
|
|
764
793
|
});
|
|
765
794
|
};
|
|
766
795
|
this.getLegendDataGroups = legendData => {
|
|
@@ -779,43 +808,77 @@ class ChartComponent extends _react.Component {
|
|
|
779
808
|
} = this.legendConfig;
|
|
780
809
|
const {
|
|
781
810
|
start,
|
|
782
|
-
end
|
|
811
|
+
end,
|
|
812
|
+
top,
|
|
813
|
+
bottom
|
|
783
814
|
} = this.getLegendBoundary(legendPosition);
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
815
|
+
if (top && bottom) {
|
|
816
|
+
let allHeight = top;
|
|
817
|
+
const groupsData = [];
|
|
818
|
+
const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
|
|
819
|
+
let lastIndex = 0;
|
|
820
|
+
legendData.forEach((item, index) => {
|
|
821
|
+
const virtualLegend = this.chart.append('g').attr('opacity', 0);
|
|
822
|
+
virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
|
|
823
|
+
virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
|
|
824
|
+
const {
|
|
825
|
+
height
|
|
826
|
+
} = virtualLegend.node().getBoundingClientRect();
|
|
827
|
+
const itemHeight = index === legendData.length - 1 ? height : height + legendItemMargin; // last item no used margin
|
|
828
|
+
allHeight = allHeight + itemHeight;
|
|
829
|
+
if (allHeight > bottom) {
|
|
830
|
+
groupsData.push(newLegendData.slice(0, index - lastIndex));
|
|
831
|
+
newLegendData.splice(0, index - lastIndex);
|
|
832
|
+
lastIndex = index;
|
|
833
|
+
allHeight = top + itemHeight;
|
|
834
|
+
}
|
|
835
|
+
virtualLegend.remove();
|
|
836
|
+
});
|
|
837
|
+
const restLegendItems = newLegendData.slice(0);
|
|
838
|
+
restLegendItems.length !== 0 && groupsData.push(restLegendItems);
|
|
839
|
+
return groupsData;
|
|
840
|
+
} else {
|
|
841
|
+
let allWidth = start;
|
|
842
|
+
const groupsData = [];
|
|
843
|
+
const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
|
|
844
|
+
let lastIndex = 0;
|
|
845
|
+
legendData.forEach((item, index) => {
|
|
846
|
+
const virtualLegend = this.chart.append('g').attr('opacity', 0);
|
|
847
|
+
virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
|
|
848
|
+
virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
|
|
849
|
+
const {
|
|
850
|
+
width
|
|
851
|
+
} = virtualLegend.node().getBoundingClientRect();
|
|
852
|
+
const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
|
|
853
|
+
allWidth = allWidth + itemWidth;
|
|
854
|
+
if (allWidth > end) {
|
|
855
|
+
groupsData.push(newLegendData.slice(0, index - lastIndex));
|
|
856
|
+
newLegendData.splice(0, index - lastIndex);
|
|
857
|
+
lastIndex = index;
|
|
858
|
+
allWidth = start + itemWidth;
|
|
859
|
+
}
|
|
860
|
+
virtualLegend.remove();
|
|
861
|
+
});
|
|
862
|
+
const restLegendItems = newLegendData.slice(0);
|
|
863
|
+
restLegendItems.length !== 0 && groupsData.push(restLegendItems);
|
|
864
|
+
return groupsData;
|
|
865
|
+
}
|
|
808
866
|
};
|
|
809
867
|
this.getLegendBoundary = legendPosition => {
|
|
810
868
|
const {
|
|
811
|
-
legendPageNavWrapperWidth
|
|
869
|
+
legendPageNavWrapperWidth,
|
|
870
|
+
legendPageNavWrapperHeight
|
|
812
871
|
} = this.legendConfig;
|
|
813
872
|
const {
|
|
814
873
|
width: chartWidth,
|
|
815
|
-
|
|
874
|
+
height: chartHeight,
|
|
875
|
+
insertPadding,
|
|
876
|
+
rightLegendSpace
|
|
816
877
|
} = this.chartBoundingClientRect;
|
|
817
878
|
let start = 0;
|
|
818
879
|
let end = 0;
|
|
880
|
+
let top = 0;
|
|
881
|
+
let bottom = 0;
|
|
819
882
|
if (legendPosition === 'top-left') {
|
|
820
883
|
start = insertPadding;
|
|
821
884
|
end = chartWidth - insertPadding - legendPageNavWrapperWidth;
|
|
@@ -824,9 +887,17 @@ class ChartComponent extends _react.Component {
|
|
|
824
887
|
start = insertPadding + legendPageNavWrapperWidth;
|
|
825
888
|
end = chartWidth - insertPadding;
|
|
826
889
|
}
|
|
890
|
+
if (legendPosition === 'center-right') {
|
|
891
|
+
start = chartWidth - insertPadding - rightLegendSpace;
|
|
892
|
+
end = chartWidth - insertPadding;
|
|
893
|
+
top = insertPadding;
|
|
894
|
+
bottom = chartHeight - insertPadding - legendPageNavWrapperHeight;
|
|
895
|
+
}
|
|
827
896
|
return {
|
|
828
897
|
start,
|
|
829
|
-
end
|
|
898
|
+
end,
|
|
899
|
+
top,
|
|
900
|
+
bottom
|
|
830
901
|
};
|
|
831
902
|
};
|
|
832
903
|
this.handleNavigatorOpacity = (navigator, text) => {
|
|
@@ -1318,6 +1389,26 @@ class ChartComponent extends _react.Component {
|
|
|
1318
1389
|
}
|
|
1319
1390
|
}
|
|
1320
1391
|
};
|
|
1392
|
+
this.ticksAddName = g => {
|
|
1393
|
+
if (g.selectAll('.tick')) {
|
|
1394
|
+
const ticks = g.selectAll('.tick').nodes();
|
|
1395
|
+
ticks.forEach(tick => {
|
|
1396
|
+
var _d3$select$select;
|
|
1397
|
+
const text = (_d3$select$select = d3.select(tick).select('text')) === null || _d3$select$select === void 0 ? void 0 : _d3$select$select.node();
|
|
1398
|
+
d3.select(tick).select('line').attr('data-name', text.innerHTML);
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
this.getMinDistanceItem = (offsetX, allData) => {
|
|
1403
|
+
// allData = [{x: number}]
|
|
1404
|
+
const newAllData = allData.filter(item => Object.keys(item).length !== 0);
|
|
1405
|
+
newAllData.forEach(item => {
|
|
1406
|
+
item['distance'] = Math.abs(item.x - offsetX);
|
|
1407
|
+
});
|
|
1408
|
+
const minIndex = d3.minIndex(newAllData, d => d.distance);
|
|
1409
|
+
const minItem = newAllData[minIndex];
|
|
1410
|
+
return minItem;
|
|
1411
|
+
};
|
|
1321
1412
|
this.initLabelStroke(props === null || props === void 0 ? void 0 : props.globalTheme);
|
|
1322
1413
|
this.chartBoundingClientRect = {};
|
|
1323
1414
|
}
|