sea-chart 2.0.9 → 2.0.11
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/api/index.js +1 -1
- package/dist/components/types-dialog/index.js +2 -1
- package/dist/constants/index.js +1 -1
- package/dist/utils/sql/chart-data-sql.js +2 -1
- package/dist/view/wrapper/bar-compare.js +42 -29
- package/dist/view/wrapper/bar-custom-stack.js +98 -45
- package/dist/view/wrapper/bar-group.js +44 -28
- package/dist/view/wrapper/bar-stack.js +62 -21
- package/dist/view/wrapper/bar.js +29 -30
- package/dist/view/wrapper/chart-component.js +460 -87
- package/dist/view/wrapper/horizontal-bar-group.js +282 -0
- package/dist/view/wrapper/horizontal-bar.js +266 -0
- package/dist/view/wrapper/index.js +30 -2
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ var _dtableUtils = require("dtable-utils");
|
|
|
13
13
|
var _utils = require("../../utils");
|
|
14
14
|
var _constants = require("../../constants");
|
|
15
15
|
var _intl = _interopRequireDefault(require("../../intl"));
|
|
16
|
+
var _columnUtils = require("../../utils/column-utils");
|
|
16
17
|
require("../../assets/css/sea-chart-d3-tooltip.css");
|
|
17
18
|
class ChartComponent extends _react.Component {
|
|
18
19
|
constructor(props) {
|
|
@@ -51,14 +52,22 @@ class ChartComponent extends _react.Component {
|
|
|
51
52
|
this.initChart = function (container, id) {
|
|
52
53
|
let initConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
53
54
|
const {
|
|
54
|
-
width,
|
|
55
|
-
height
|
|
55
|
+
width: containerWidth,
|
|
56
|
+
height: containerHeight
|
|
56
57
|
} = container.getBoundingClientRect();
|
|
58
|
+
const {
|
|
59
|
+
marginLeft = 0,
|
|
60
|
+
marginBottom = 0
|
|
61
|
+
} = initConfig;
|
|
62
|
+
const width = containerWidth - marginLeft;
|
|
63
|
+
const height = containerHeight - marginBottom;
|
|
57
64
|
_this.chart = d3.create('svg').attr('id', id).attr('class', "svg-wrapper-".concat(id)).attr('width', width).attr('height', height).attr('viewBox', [0, 0, width, height]);
|
|
58
65
|
_this.container.appendChild(_this.chart.node());
|
|
59
66
|
_this.chartBoundingClientRect = {
|
|
60
67
|
...JSON.parse(JSON.stringify(_this.chart.node().getBoundingClientRect())),
|
|
61
|
-
...initConfig
|
|
68
|
+
...initConfig,
|
|
69
|
+
width,
|
|
70
|
+
height
|
|
62
71
|
};
|
|
63
72
|
};
|
|
64
73
|
this.initDefs = () => {
|
|
@@ -70,7 +79,7 @@ class ChartComponent extends _react.Component {
|
|
|
70
79
|
const {
|
|
71
80
|
width,
|
|
72
81
|
height
|
|
73
|
-
} = this.
|
|
82
|
+
} = this.chartBoundingClientRect;
|
|
74
83
|
this.chart.append('defs').append('mask').attr('id', "mask-wrapper-".concat(previewType, "-").concat(this.chart.node().id)).append('rect').attr('x', 0).attr('y', 0).attr('width', width).attr('height', height - 30).attr('fill', 'white');
|
|
75
84
|
}
|
|
76
85
|
};
|
|
@@ -216,7 +225,6 @@ class ChartComponent extends _react.Component {
|
|
|
216
225
|
}
|
|
217
226
|
};
|
|
218
227
|
this.renderAxisLabel = (chart, tables, chartContainer) => {
|
|
219
|
-
var _this$chart2;
|
|
220
228
|
if (!this.chart || !chart) return;
|
|
221
229
|
let {
|
|
222
230
|
table_id,
|
|
@@ -237,30 +245,31 @@ class ChartComponent extends _react.Component {
|
|
|
237
245
|
y_axis_column_key = y_axis_summary_column_key;
|
|
238
246
|
}
|
|
239
247
|
const table = (0, _dtableUtils.getTableById)(tables, table_id);
|
|
240
|
-
const autoPadding = ((_this$chart2 = this.chart) === null || _this$chart2 === void 0 ? void 0 : _this$chart2.autoPadding) || {
|
|
241
|
-
bottom: 0
|
|
242
|
-
};
|
|
243
248
|
let textColor;
|
|
244
249
|
this.globalTheme === _constants.THEME_NAME_MAP.DARK ? textColor = '#fff' : textColor = '#999';
|
|
245
250
|
const xAxisID = "chart-x-axis-label_".concat(chart.id);
|
|
246
251
|
const xLabel = chartContainer === null || chartContainer === void 0 ? void 0 : chartContainer.querySelector("#".concat(xAxisID));
|
|
252
|
+
const {
|
|
253
|
+
width: containerWidth
|
|
254
|
+
} = this.chartBoundingClientRect;
|
|
247
255
|
if (!xLabel && x_axis_show_label) {
|
|
248
256
|
const div = document.createElement('div');
|
|
249
257
|
div.id = xAxisID;
|
|
250
258
|
div.className = 'chart-axis-label';
|
|
251
259
|
const column = (0, _dtableUtils.getTableColumnByKey)(table, x_axis_column_key);
|
|
252
260
|
div.innerHTML = "".concat(column ? column.name : '');
|
|
253
|
-
div.setAttribute('style', "color:".concat(textColor, "; width:
|
|
261
|
+
div.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(x_axis_label_position, "; position: absolute"));
|
|
254
262
|
chartContainer.appendChild(div);
|
|
255
263
|
}
|
|
256
264
|
if (xLabel && x_axis_show_label) {
|
|
257
|
-
xLabel.setAttribute('style', "color:".concat(textColor, "; width:
|
|
265
|
+
xLabel.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(x_axis_label_position, "; position: absolute"));
|
|
258
266
|
}
|
|
259
267
|
if (xLabel && !x_axis_show_label) {
|
|
260
268
|
xLabel.parentNode.removeChild(xLabel);
|
|
261
269
|
}
|
|
262
270
|
const yAxisID = "chart-y-axis-label_".concat(chart.id);
|
|
263
271
|
const yLabel = chartContainer.querySelector("#".concat(yAxisID));
|
|
272
|
+
const divHeight = 20;
|
|
264
273
|
if (!yLabel && y_axis_show_label) {
|
|
265
274
|
const div = document.createElement('div');
|
|
266
275
|
div.id = yAxisID;
|
|
@@ -274,24 +283,103 @@ class ChartComponent extends _react.Component {
|
|
|
274
283
|
div.innerHTML = title_name || '';
|
|
275
284
|
}
|
|
276
285
|
}
|
|
277
|
-
const
|
|
286
|
+
const {
|
|
287
|
+
height: containerHeight
|
|
288
|
+
} = this.chartBoundingClientRect;
|
|
278
289
|
let textAlign = 'center';
|
|
279
290
|
if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
|
|
280
291
|
if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
|
|
281
|
-
div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2
|
|
292
|
+
div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
|
|
282
293
|
chartContainer.appendChild(div);
|
|
283
294
|
}
|
|
284
295
|
if (yLabel && y_axis_show_label) {
|
|
285
|
-
const
|
|
296
|
+
const {
|
|
297
|
+
height: containerHeight
|
|
298
|
+
} = this.chartBoundingClientRect;
|
|
286
299
|
let textAlign = 'center';
|
|
287
300
|
if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
|
|
288
301
|
if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
|
|
289
|
-
yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2
|
|
302
|
+
yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
|
|
290
303
|
}
|
|
291
304
|
if (yLabel && !y_axis_show_label) {
|
|
292
305
|
yLabel.parentNode.removeChild(yLabel);
|
|
293
306
|
}
|
|
294
307
|
};
|
|
308
|
+
this.renderHorizontalLabel = (chart, tables, chartContainer) => {
|
|
309
|
+
if (!this.chart || !chart) return;
|
|
310
|
+
const {
|
|
311
|
+
table_id,
|
|
312
|
+
vertical_axis_column_key,
|
|
313
|
+
horizontal_axis_column_key,
|
|
314
|
+
horizontal_axis_summary_type,
|
|
315
|
+
horizontal_axis_label_position,
|
|
316
|
+
vertical_axis_label_position,
|
|
317
|
+
show_vertical_axis_label,
|
|
318
|
+
show_horizontal_axis_label
|
|
319
|
+
} = chart.config;
|
|
320
|
+
const table = (0, _dtableUtils.getTableById)(tables, table_id);
|
|
321
|
+
const textColor = '#999999';
|
|
322
|
+
const xAxisID = "chart-x-axis-label_".concat(chart.id);
|
|
323
|
+
const xLabel = chartContainer.querySelector("#".concat(xAxisID));
|
|
324
|
+
const {
|
|
325
|
+
width: containerWidth
|
|
326
|
+
} = this.chartBoundingClientRect;
|
|
327
|
+
if (!xLabel && show_horizontal_axis_label) {
|
|
328
|
+
const div = document.createElement('div');
|
|
329
|
+
div.id = xAxisID;
|
|
330
|
+
div.className = 'chart-axis-label';
|
|
331
|
+
if (horizontal_axis_summary_type === _constants.CHART_SUMMARY_TYPE.COUNT) {
|
|
332
|
+
div.innerHTML = _intl.default.get('Amount');
|
|
333
|
+
} else {
|
|
334
|
+
const column = (0, _dtableUtils.getTableColumnByKey)(table, horizontal_axis_column_key);
|
|
335
|
+
div.innerHTML = "".concat(column ? column.name : '');
|
|
336
|
+
}
|
|
337
|
+
div.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(horizontal_axis_label_position, "; position: absolute"));
|
|
338
|
+
chartContainer.appendChild(div);
|
|
339
|
+
}
|
|
340
|
+
if (xLabel && show_horizontal_axis_label) {
|
|
341
|
+
xLabel.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(horizontal_axis_label_position, "; position: absolute"));
|
|
342
|
+
}
|
|
343
|
+
if (xLabel && !show_horizontal_axis_label) {
|
|
344
|
+
xLabel.parentNode.removeChild(xLabel);
|
|
345
|
+
}
|
|
346
|
+
const yAxisID = "chart-y-axis-label_".concat(chart.id);
|
|
347
|
+
const yLabel = chartContainer.querySelector("#".concat(yAxisID));
|
|
348
|
+
const divHeight = 20;
|
|
349
|
+
if (!yLabel && show_vertical_axis_label) {
|
|
350
|
+
const div = document.createElement('div');
|
|
351
|
+
div.id = yAxisID;
|
|
352
|
+
div.className = 'chart-axis-label';
|
|
353
|
+
const column = (0, _dtableUtils.getTableColumnByKey)(table, vertical_axis_column_key) || {};
|
|
354
|
+
div.innerHTML = column.name || '';
|
|
355
|
+
const {
|
|
356
|
+
height: containerHeight
|
|
357
|
+
} = this.chartBoundingClientRect;
|
|
358
|
+
let textAlign = 'center';
|
|
359
|
+
if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
|
|
360
|
+
if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
|
|
361
|
+
div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
|
|
362
|
+
chartContainer.appendChild(div);
|
|
363
|
+
}
|
|
364
|
+
if (yLabel && show_horizontal_axis_label) {
|
|
365
|
+
const {
|
|
366
|
+
height: containerHeight
|
|
367
|
+
} = this.chartBoundingClientRect;
|
|
368
|
+
let textAlign = 'center';
|
|
369
|
+
if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
|
|
370
|
+
if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
|
|
371
|
+
yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
|
|
372
|
+
}
|
|
373
|
+
if (yLabel && !show_horizontal_axis_label) {
|
|
374
|
+
yLabel.parentNode.removeChild(yLabel);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
this.isShowVerticalAxisLabel = chart => {
|
|
378
|
+
return !!(chart && chart.config && chart.config.show_vertical_axis_label);
|
|
379
|
+
};
|
|
380
|
+
this.isShowHorizontalAxisLabel = chart => {
|
|
381
|
+
return !!(chart && chart.config && chart.config.show_horizontal_axis_label);
|
|
382
|
+
};
|
|
295
383
|
// Automatic adjustment of maximum and minimum values
|
|
296
384
|
this.autoAdjustDataOptions = function (chart) {
|
|
297
385
|
let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
@@ -481,93 +569,292 @@ class ChartComponent extends _react.Component {
|
|
|
481
569
|
return _intl.default.get(name) || name;
|
|
482
570
|
}
|
|
483
571
|
};
|
|
484
|
-
this.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
} = item.getBoundingClientRect();
|
|
497
|
-
width = width + legendItemWidth;
|
|
572
|
+
this.sortLegend = (result, groupColumn, legendName) => {
|
|
573
|
+
result.forEach(item => {
|
|
574
|
+
const option = groupColumn.data.options.find(option => option.name === item[legendName]);
|
|
575
|
+
if (option !== null && option !== void 0 && option.id) {
|
|
576
|
+
item['group_name_id'] = option.id;
|
|
577
|
+
item['oldName'] = item.name;
|
|
578
|
+
item.name = item['group_name_id'];
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
_utils.BaseUtils.sortCharts(result, groupColumn, 'name');
|
|
582
|
+
result.forEach(item => {
|
|
583
|
+
item.name = item['oldName'];
|
|
498
584
|
});
|
|
499
|
-
return width;
|
|
500
585
|
};
|
|
501
586
|
// set legend
|
|
502
|
-
this.setLegend =
|
|
587
|
+
this.setLegend = _ref => {
|
|
503
588
|
var _this$chart$node;
|
|
504
|
-
let
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
589
|
+
let {
|
|
590
|
+
legendName,
|
|
591
|
+
theme = _constants.CHART_THEME_COLOR['light'],
|
|
592
|
+
legendPosition = 'top-left',
|
|
593
|
+
data,
|
|
594
|
+
colorScale,
|
|
595
|
+
groupColumn
|
|
596
|
+
} = _ref;
|
|
597
|
+
if (!this.chart) return;
|
|
598
|
+
const legendData = (0, _lodashEs.cloneDeep)(data);
|
|
599
|
+
this.legendConfig = {
|
|
600
|
+
legendRectWidth: 20,
|
|
601
|
+
legendRectHeight: 6,
|
|
602
|
+
r: 3,
|
|
603
|
+
legendItemPaddingTop: 3,
|
|
604
|
+
legendItemMargin: 20,
|
|
605
|
+
legendRecTextGap: 8,
|
|
606
|
+
legendPageNavWrapperWidth: 100,
|
|
607
|
+
legendPosition,
|
|
608
|
+
legendName,
|
|
609
|
+
theme
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// sort legend data
|
|
613
|
+
if (groupColumn && [_dtableUtils.CellType.SINGLE_SELECT].includes(groupColumn.type)) {
|
|
614
|
+
this.sortLegend(legendData, groupColumn, legendName);
|
|
615
|
+
}
|
|
509
616
|
const {
|
|
510
617
|
width: chartWidth,
|
|
511
618
|
insertPadding
|
|
512
|
-
} =
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
619
|
+
} = this.chartBoundingClientRect;
|
|
620
|
+
const groupsData = this.getLegendDataGroups(legendData);
|
|
621
|
+
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));
|
|
622
|
+
|
|
623
|
+
// Render first group legend
|
|
624
|
+
this.renderLegend({
|
|
625
|
+
legendWrapper,
|
|
626
|
+
groupData: groupsData[0],
|
|
627
|
+
colorScale,
|
|
628
|
+
theme
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
// Render Page navigator
|
|
632
|
+
if (groupsData.length > 1) {
|
|
633
|
+
const {
|
|
634
|
+
legendPageNavWrapperWidth
|
|
635
|
+
} = this.legendConfig;
|
|
636
|
+
let curCount = 0;
|
|
637
|
+
const pageNavigator = legendWrapper.append('g').attr('class', 'legend-flip-page');
|
|
638
|
+
|
|
639
|
+
// count
|
|
640
|
+
pageNavigator.append('text').attr('class', 'legend-count').attr('dominant-baseline', 'hanging').attr('x', 15).attr('fill', theme.legendTextColor).attr('font-size', theme.legendFontSize).text("".concat(curCount + 1, "/").concat(groupsData.length));
|
|
641
|
+
|
|
642
|
+
// prev page
|
|
643
|
+
pageNavigator.append('polygon').attr('class', 'legend-prev-page').attr('points', this.calcEquilateralTriangle(5, 5, 12)).attr('fill', theme.legendPageNavigatorMarkerColor).attr('opacity', curCount === 0 ? 0.45 : 1).attr('style', 'cursor: pointer;').on('click', event => {
|
|
644
|
+
if (curCount > 0) {
|
|
645
|
+
curCount--;
|
|
646
|
+
this.renderLegend({
|
|
647
|
+
legendWrapper,
|
|
648
|
+
groupData: groupsData[curCount],
|
|
649
|
+
colorScale,
|
|
650
|
+
theme,
|
|
651
|
+
text: "".concat(curCount + 1, "/").concat(groupsData.length)
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
// next page
|
|
657
|
+
pageNavigator.append('polygon').attr('class', 'legend-next-page').attr('points', this.calcEquilateralTriangle(45, 5, 12, 'bottom')).attr('fill', theme.legendPageNavigatorMarkerColor).attr('opacity', curCount === groupsData.length - 1 ? 0.45 : 1).attr('style', 'cursor: pointer;').on('click', event => {
|
|
658
|
+
if (curCount < groupsData.length - 1) {
|
|
659
|
+
curCount++;
|
|
660
|
+
this.renderLegend({
|
|
661
|
+
legendWrapper,
|
|
662
|
+
groupData: groupsData[curCount],
|
|
663
|
+
colorScale,
|
|
664
|
+
theme,
|
|
665
|
+
text: "".concat(curCount + 1, "/").concat(groupsData.length)
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
// update pageNavigator transform
|
|
671
|
+
pageNavigator.call(g => {
|
|
672
|
+
let groupTranslateX = 0;
|
|
673
|
+
if (legendPosition === 'top-right') {
|
|
674
|
+
groupTranslateX = insertPadding;
|
|
675
|
+
} else if (legendPosition === 'top-left') {
|
|
676
|
+
groupTranslateX = chartWidth - insertPadding - legendPageNavWrapperWidth;
|
|
677
|
+
const {
|
|
678
|
+
width
|
|
679
|
+
} = g.node().getBoundingClientRect();
|
|
680
|
+
const offset = legendPageNavWrapperWidth - width;
|
|
681
|
+
groupTranslateX = groupTranslateX + offset;
|
|
682
|
+
}
|
|
683
|
+
g.attr('transform', "translate(".concat(groupTranslateX, ", 0)"));
|
|
684
|
+
});
|
|
525
685
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
686
|
+
};
|
|
687
|
+
this.renderLegend = _ref2 => {
|
|
688
|
+
let {
|
|
689
|
+
legendWrapper,
|
|
690
|
+
groupData,
|
|
691
|
+
colorScale,
|
|
692
|
+
theme,
|
|
693
|
+
text
|
|
694
|
+
} = _ref2;
|
|
695
|
+
const {
|
|
696
|
+
legendItemPaddingTop,
|
|
697
|
+
legendRectWidth,
|
|
698
|
+
legendRectHeight,
|
|
699
|
+
r,
|
|
700
|
+
legendRecTextGap,
|
|
701
|
+
legendItemMargin,
|
|
702
|
+
legendPosition
|
|
703
|
+
} = this.legendConfig;
|
|
704
|
+
|
|
705
|
+
// clear old legends
|
|
706
|
+
const oldChildren = Array.from(legendWrapper.node().children);
|
|
707
|
+
if (oldChildren.length !== 0) {
|
|
708
|
+
oldChildren.forEach(item => {
|
|
709
|
+
// update navigator button opacity and text
|
|
710
|
+
if (item.getAttribute('class') == 'legend-flip-page') {
|
|
711
|
+
this.handleNavigatorOpacity(item, text);
|
|
712
|
+
d3.select(item).selectAll('text').text(text);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
// remove old legend item
|
|
716
|
+
d3.select(item).remove();
|
|
717
|
+
});
|
|
530
718
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
719
|
+
legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName', _ref3 => {
|
|
720
|
+
let [groupName] = _ref3;
|
|
721
|
+
return groupName;
|
|
722
|
+
}).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref4 => {
|
|
723
|
+
let [groupName] = _ref4;
|
|
534
724
|
if (colorScale) return colorScale(groupName);
|
|
535
|
-
return
|
|
536
|
-
}).attr('data-text',
|
|
537
|
-
let [groupName] =
|
|
725
|
+
return this.colorMap[groupName] || _constants.CHART_STYLE_COLORS[0];
|
|
726
|
+
}).attr('data-text', _ref5 => {
|
|
727
|
+
let [groupName] = _ref5;
|
|
538
728
|
return groupName;
|
|
539
729
|
}).call(g => {
|
|
540
|
-
const legendItems = Array.from(legendWrapper.node().children);
|
|
541
|
-
const legendItemCount = legendItems.length;
|
|
542
|
-
|
|
543
730
|
// Add text
|
|
544
731
|
g.nodes().forEach(rect => {
|
|
545
732
|
const parentNode = rect.parentNode;
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
733
|
+
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
|
+
});
|
|
735
|
+
// update g translateX
|
|
736
|
+
const legendItems = Array.from(legendWrapper.node().children).filter(item => item.getAttribute('class') !== 'legend-flip-page');
|
|
737
|
+
const {
|
|
738
|
+
start,
|
|
739
|
+
end
|
|
740
|
+
} = this.getLegendBoundary(legendPosition);
|
|
741
|
+
legendItems.forEach((item, index) => {
|
|
742
|
+
let translateX = start;
|
|
743
|
+
const lastItem = legendItems[index - 1];
|
|
744
|
+
if (index > 0) {
|
|
550
745
|
const {
|
|
551
|
-
height,
|
|
552
746
|
width
|
|
553
|
-
} =
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
});
|
|
558
|
-
});
|
|
747
|
+
} = lastItem.getBoundingClientRect();
|
|
748
|
+
const prevTranslateX = Number(lastItem.getAttribute('data-translateX'));
|
|
749
|
+
translateX = prevTranslateX + width + legendItemMargin;
|
|
750
|
+
}
|
|
559
751
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
752
|
+
// legend items add offset
|
|
753
|
+
if (legendPosition === 'top-right') {
|
|
754
|
+
d3.select(item).attr('opacity', 0);
|
|
755
|
+
if (index === legendItems.length - 1) {
|
|
756
|
+
queueMicrotask(() => {
|
|
757
|
+
this.setLegendItemOffset(legendItems, end);
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
d3.select(item).attr('transform', "translate(".concat(translateX, ",0)")).attr('data-translateX', translateX);
|
|
568
762
|
});
|
|
569
763
|
});
|
|
570
764
|
};
|
|
765
|
+
this.getLegendDataGroups = legendData => {
|
|
766
|
+
const {
|
|
767
|
+
legendName,
|
|
768
|
+
theme,
|
|
769
|
+
legendPosition
|
|
770
|
+
} = this.legendConfig;
|
|
771
|
+
legendData = d3.groups(legendData, d => d[legendName]);
|
|
772
|
+
const {
|
|
773
|
+
legendItemMargin,
|
|
774
|
+
legendRectWidth,
|
|
775
|
+
legendRectHeight,
|
|
776
|
+
r,
|
|
777
|
+
legendRecTextGap
|
|
778
|
+
} = this.legendConfig;
|
|
779
|
+
const {
|
|
780
|
+
start,
|
|
781
|
+
end
|
|
782
|
+
} = this.getLegendBoundary(legendPosition);
|
|
783
|
+
let allWidth = start;
|
|
784
|
+
const groupsData = [];
|
|
785
|
+
const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
|
|
786
|
+
let lastIndex = 0;
|
|
787
|
+
legendData.forEach((item, index) => {
|
|
788
|
+
const virtualLegend = this.chart.append('g').attr('opacity', 0);
|
|
789
|
+
virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
|
|
790
|
+
virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
|
|
791
|
+
const {
|
|
792
|
+
width
|
|
793
|
+
} = virtualLegend.node().getBoundingClientRect();
|
|
794
|
+
const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
|
|
795
|
+
allWidth = allWidth + itemWidth;
|
|
796
|
+
if (allWidth > end) {
|
|
797
|
+
groupsData.push(newLegendData.slice(0, index - lastIndex));
|
|
798
|
+
newLegendData.splice(0, index - lastIndex);
|
|
799
|
+
lastIndex = index;
|
|
800
|
+
allWidth = start + itemWidth;
|
|
801
|
+
}
|
|
802
|
+
virtualLegend.remove();
|
|
803
|
+
});
|
|
804
|
+
const restLegendItems = newLegendData.slice(0);
|
|
805
|
+
restLegendItems.length !== 0 && groupsData.push(restLegendItems);
|
|
806
|
+
return groupsData;
|
|
807
|
+
};
|
|
808
|
+
this.getLegendBoundary = legendPosition => {
|
|
809
|
+
const {
|
|
810
|
+
legendPageNavWrapperWidth
|
|
811
|
+
} = this.legendConfig;
|
|
812
|
+
const {
|
|
813
|
+
width: chartWidth,
|
|
814
|
+
insertPadding
|
|
815
|
+
} = this.chartBoundingClientRect;
|
|
816
|
+
let start = 0;
|
|
817
|
+
let end = 0;
|
|
818
|
+
if (legendPosition === 'top-left') {
|
|
819
|
+
start = insertPadding;
|
|
820
|
+
end = chartWidth - insertPadding - legendPageNavWrapperWidth;
|
|
821
|
+
}
|
|
822
|
+
if (legendPosition === 'top-right') {
|
|
823
|
+
start = insertPadding + legendPageNavWrapperWidth;
|
|
824
|
+
end = chartWidth - insertPadding;
|
|
825
|
+
}
|
|
826
|
+
return {
|
|
827
|
+
start,
|
|
828
|
+
end
|
|
829
|
+
};
|
|
830
|
+
};
|
|
831
|
+
this.handleNavigatorOpacity = (navigator, text) => {
|
|
832
|
+
const curCount = text.split('/')[0];
|
|
833
|
+
const allCount = text.split('/')[1];
|
|
834
|
+
if (Number(curCount) === 0) {
|
|
835
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 0.45);
|
|
836
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
|
|
837
|
+
} else if (Number(curCount) === Number(allCount)) {
|
|
838
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
|
|
839
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 0.45);
|
|
840
|
+
} else {
|
|
841
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
|
|
842
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
this.setLegendItemOffset = (legendItems, end) => {
|
|
846
|
+
const endItem = legendItems[legendItems.length - 1];
|
|
847
|
+
const endTranslateX = Number(endItem.getAttribute('data-translateX'));
|
|
848
|
+
const {
|
|
849
|
+
width: endWidth
|
|
850
|
+
} = endItem.getBoundingClientRect();
|
|
851
|
+
const offset = end - (endTranslateX + endWidth);
|
|
852
|
+
legendItems.forEach(legendItem => {
|
|
853
|
+
const curTranslateX = Number(legendItem.getAttribute('data-translateX')) + offset;
|
|
854
|
+
d3.select(legendItem).attr('transform', "translate(".concat(curTranslateX, ",0)")).attr('data-translateX', curTranslateX);
|
|
855
|
+
d3.select(legendItem).attr('opacity', 1);
|
|
856
|
+
});
|
|
857
|
+
};
|
|
571
858
|
// theta is pie or ring chart
|
|
572
859
|
this.setLegendForTheta = function (legendName) {
|
|
573
860
|
let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
|
|
@@ -581,6 +868,13 @@ class ChartComponent extends _react.Component {
|
|
|
581
868
|
basicLegendConfig.itemName.style.fontSize = theme.fontSize;
|
|
582
869
|
_this.chart.legend(legendName, basicLegendConfig);
|
|
583
870
|
};
|
|
871
|
+
this.calcEquilateralTriangle = (cx, cy, size, direction) => {
|
|
872
|
+
const height = size * Math.sqrt(3) / 2;
|
|
873
|
+
if (direction === 'bottom') {
|
|
874
|
+
return [[cx, cy + height / 2], [cx - size / 2, cy - height / 2], [cx + size / 2, cy - height / 2]];
|
|
875
|
+
}
|
|
876
|
+
return [[cx, cy - height / 2], [cx - size / 2, cy + height / 2], [cx + size / 2, cy + height / 2]];
|
|
877
|
+
};
|
|
584
878
|
this.setColorMap = (data, chartColorTheme) => {
|
|
585
879
|
let currentIdx = 0;
|
|
586
880
|
const defaultColors = _constants.CHART_STYLE_COLORS;
|
|
@@ -762,11 +1056,11 @@ class ChartComponent extends _react.Component {
|
|
|
762
1056
|
width: chartWidth
|
|
763
1057
|
} = this.chartBoundingClientRect;
|
|
764
1058
|
const annotationWrapper = this.chart.append('g').attr('class', "annotation-wrapper-".concat((_this$chart$node2 = this.chart.node()) === null || _this$chart$node2 === void 0 ? void 0 : _this$chart$node2.id));
|
|
765
|
-
annotationWrapper.append('line').attr('stroke', '#aaa').attr('x1', insertPadding).attr('y1', yScale(goal_value)).attr('x2', chartWidth - insertPadding).attr('y2', yScale(goal_value)).call(g => {
|
|
1059
|
+
annotationWrapper.append('line').attr('stroke', '#aaa').attr('x1', insertPadding).attr('y1', yScale(goal_value)).attr('x2', chartWidth - insertPadding).attr('y2', yScale(goal_value)).attr('stroke-dasharray', '8,3').call(g => {
|
|
766
1060
|
annotationWrapper.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
|
|
767
1061
|
});
|
|
768
1062
|
};
|
|
769
|
-
this.addLabelToRectTop =
|
|
1063
|
+
this.addLabelToRectTop = _ref6 => {
|
|
770
1064
|
let {
|
|
771
1065
|
container,
|
|
772
1066
|
x,
|
|
@@ -775,7 +1069,7 @@ class ChartComponent extends _react.Component {
|
|
|
775
1069
|
theme,
|
|
776
1070
|
label_font_size,
|
|
777
1071
|
text
|
|
778
|
-
} =
|
|
1072
|
+
} = _ref6;
|
|
779
1073
|
d3.select(container).append('text').attr('y', Number(y) - 10).attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
780
1074
|
const {
|
|
781
1075
|
width
|
|
@@ -783,7 +1077,24 @@ class ChartComponent extends _react.Component {
|
|
|
783
1077
|
g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
|
|
784
1078
|
});
|
|
785
1079
|
};
|
|
786
|
-
this.
|
|
1080
|
+
this.addLabelToRectRight = _ref7 => {
|
|
1081
|
+
let {
|
|
1082
|
+
container,
|
|
1083
|
+
y,
|
|
1084
|
+
xWidth,
|
|
1085
|
+
yHeight,
|
|
1086
|
+
theme,
|
|
1087
|
+
label_font_size,
|
|
1088
|
+
text
|
|
1089
|
+
} = _ref7;
|
|
1090
|
+
d3.select(container).append('text').attr('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 => {
|
|
1091
|
+
const {
|
|
1092
|
+
height
|
|
1093
|
+
} = g.node().getBoundingClientRect();
|
|
1094
|
+
g.attr('y', Number(y) + Number(yHeight) / 2 - height / 2);
|
|
1095
|
+
});
|
|
1096
|
+
};
|
|
1097
|
+
this.addLabelToRectCenter = _ref8 => {
|
|
787
1098
|
let {
|
|
788
1099
|
chartType,
|
|
789
1100
|
container,
|
|
@@ -791,11 +1102,10 @@ class ChartComponent extends _react.Component {
|
|
|
791
1102
|
y,
|
|
792
1103
|
xWidth,
|
|
793
1104
|
yheight,
|
|
794
|
-
overflowHeight,
|
|
795
1105
|
theme,
|
|
796
1106
|
label_font_size,
|
|
797
1107
|
text
|
|
798
|
-
} =
|
|
1108
|
+
} = _ref8;
|
|
799
1109
|
d3.select(container).append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
800
1110
|
const {
|
|
801
1111
|
width,
|
|
@@ -804,7 +1114,7 @@ class ChartComponent extends _react.Component {
|
|
|
804
1114
|
const translateX = Number(x) + xWidth / 2 - width / 2;
|
|
805
1115
|
let translateY = Number(y) + Number(yheight / 2) + height / 2;
|
|
806
1116
|
if (chartType === _constants.CHART_TYPE.BAR_STACK) {
|
|
807
|
-
translateY = translateY
|
|
1117
|
+
translateY = translateY;
|
|
808
1118
|
}
|
|
809
1119
|
g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
|
|
810
1120
|
});
|
|
@@ -829,6 +1139,69 @@ class ChartComponent extends _react.Component {
|
|
|
829
1139
|
});
|
|
830
1140
|
}
|
|
831
1141
|
};
|
|
1142
|
+
// Use clipPath to make rectangle rounded corners
|
|
1143
|
+
this.addClipPath = _ref9 => {
|
|
1144
|
+
let {
|
|
1145
|
+
rect,
|
|
1146
|
+
parentNode,
|
|
1147
|
+
attr,
|
|
1148
|
+
rectId
|
|
1149
|
+
} = _ref9;
|
|
1150
|
+
const {
|
|
1151
|
+
borderRadius
|
|
1152
|
+
} = this.chartBoundingClientRect;
|
|
1153
|
+
const clipRect = d3.select(rect.cloneNode());
|
|
1154
|
+
if (attr === 'x') {
|
|
1155
|
+
const borderRadiusVal = Number(rect.getAttribute('height')) * borderRadius;
|
|
1156
|
+
clipRect.attr('rx', borderRadiusVal);
|
|
1157
|
+
clipRect.attr('x', Number(rect.getAttribute('x')) - borderRadiusVal).attr('width', Number(rect.getAttribute('width')) + borderRadiusVal);
|
|
1158
|
+
} else {
|
|
1159
|
+
const borderRadiusVal = Number(rect.getAttribute('width')) * borderRadius;
|
|
1160
|
+
clipRect.attr('rx', borderRadiusVal);
|
|
1161
|
+
clipRect.attr('height', Number(rect.getAttribute('height')) + borderRadiusVal);
|
|
1162
|
+
}
|
|
1163
|
+
const clipPath = d3.select(parentNode).append('clipPath').attr('id', rectId);
|
|
1164
|
+
clipPath.node().appendChild(clipRect.node());
|
|
1165
|
+
d3.select(rect).attr('clip-path', "url(#".concat(rectId, ")"));
|
|
1166
|
+
};
|
|
1167
|
+
this.drawYaxis = (g, theme) => {
|
|
1168
|
+
const {
|
|
1169
|
+
width: chartWidth,
|
|
1170
|
+
insertPadding
|
|
1171
|
+
} = this.chartBoundingClientRect;
|
|
1172
|
+
// remove domain
|
|
1173
|
+
g.select('.domain').remove();
|
|
1174
|
+
|
|
1175
|
+
// add text
|
|
1176
|
+
g.selectAll('text').attr('font-size', theme.fontSize);
|
|
1177
|
+
g.selectAll('text').attr('fill', theme.textColor);
|
|
1178
|
+
this.checkTextOverflow(g.selectAll('text').nodes());
|
|
1179
|
+
|
|
1180
|
+
// line
|
|
1181
|
+
g.selectAll('line').node() && g.selectAll('line').node().remove(); // delete the first line
|
|
1182
|
+
g.selectAll('.tick line').clone().attr('x2', chartWidth - insertPadding * 2 - this.horizontalOverflowOffset).attr('stroke', theme.gridColor).attr('stroke-dasharray', '8,3');
|
|
1183
|
+
|
|
1184
|
+
// update g translateX
|
|
1185
|
+
g.attr('transform', "translate(".concat(insertPadding + this.horizontalOverflowOffset, ", 0)"));
|
|
1186
|
+
};
|
|
1187
|
+
this.checkTextOverflow = allTextEl => {
|
|
1188
|
+
const {
|
|
1189
|
+
insertPadding
|
|
1190
|
+
} = this.chartBoundingClientRect;
|
|
1191
|
+
const allTextWidth = allTextEl.map(item => {
|
|
1192
|
+
const {
|
|
1193
|
+
width
|
|
1194
|
+
} = item.getBoundingClientRect();
|
|
1195
|
+
return width;
|
|
1196
|
+
});
|
|
1197
|
+
const maxTextWidth = Math.max(...allTextWidth);
|
|
1198
|
+
this.horizontalOverflowOffset = 0;
|
|
1199
|
+
if (maxTextWidth > insertPadding) {
|
|
1200
|
+
// horizontal overflow
|
|
1201
|
+
const offset = maxTextWidth + 3 - insertPadding; // 3 is text and line default spacing
|
|
1202
|
+
this.horizontalOverflowOffset = offset;
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
832
1205
|
this.initLabelStroke(props === null || props === void 0 ? void 0 : props.globalTheme);
|
|
833
1206
|
this.chartBoundingClientRect = {};
|
|
834
1207
|
}
|