sea-chart 2.0.9 → 2.0.10
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/types-dialog/index.js +2 -1
- package/dist/constants/index.js +1 -1
- package/dist/view/wrapper/bar-compare.js +36 -17
- package/dist/view/wrapper/bar-custom-stack.js +89 -30
- package/dist/view/wrapper/bar-group.js +40 -18
- package/dist/view/wrapper/bar-stack.js +31 -8
- package/dist/view/wrapper/bar.js +28 -23
- package/dist/view/wrapper/chart-component.js +420 -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 +27 -0
- 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,290 @@ 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
|
+
legendData.forEach((item, index) => {
|
|
787
|
+
const virtualLegend = this.chart.append('g').attr('opacity', 0);
|
|
788
|
+
virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
|
|
789
|
+
virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
|
|
790
|
+
const {
|
|
791
|
+
width
|
|
792
|
+
} = virtualLegend.node().getBoundingClientRect();
|
|
793
|
+
const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
|
|
794
|
+
allWidth = allWidth + itemWidth;
|
|
795
|
+
if (allWidth >= end) {
|
|
796
|
+
groupsData.push(newLegendData.slice(0, index));
|
|
797
|
+
newLegendData.splice(0, index);
|
|
798
|
+
allWidth = 0;
|
|
799
|
+
}
|
|
800
|
+
virtualLegend.remove();
|
|
801
|
+
});
|
|
802
|
+
const restLegendItems = newLegendData.slice(0);
|
|
803
|
+
groupsData.push(restLegendItems);
|
|
804
|
+
return groupsData;
|
|
805
|
+
};
|
|
806
|
+
this.getLegendBoundary = legendPosition => {
|
|
807
|
+
const {
|
|
808
|
+
legendPageNavWrapperWidth
|
|
809
|
+
} = this.legendConfig;
|
|
810
|
+
const {
|
|
811
|
+
width: chartWidth,
|
|
812
|
+
insertPadding
|
|
813
|
+
} = this.chartBoundingClientRect;
|
|
814
|
+
let start = 0;
|
|
815
|
+
let end = 0;
|
|
816
|
+
if (legendPosition === 'top-left') {
|
|
817
|
+
start = insertPadding;
|
|
818
|
+
end = chartWidth - insertPadding - legendPageNavWrapperWidth;
|
|
819
|
+
}
|
|
820
|
+
if (legendPosition === 'top-right') {
|
|
821
|
+
start = insertPadding + legendPageNavWrapperWidth;
|
|
822
|
+
end = chartWidth - insertPadding;
|
|
823
|
+
}
|
|
824
|
+
return {
|
|
825
|
+
start,
|
|
826
|
+
end
|
|
827
|
+
};
|
|
828
|
+
};
|
|
829
|
+
this.handleNavigatorOpacity = (navigator, text) => {
|
|
830
|
+
const curCount = text.split('/')[0];
|
|
831
|
+
const allCount = text.split('/')[1];
|
|
832
|
+
if (Number(curCount) === 0) {
|
|
833
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 0.45);
|
|
834
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
|
|
835
|
+
} else if (Number(curCount) === Number(allCount)) {
|
|
836
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
|
|
837
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 0.45);
|
|
838
|
+
} else {
|
|
839
|
+
d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
|
|
840
|
+
d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
this.setLegendItemOffset = (legendItems, end) => {
|
|
844
|
+
const endItem = legendItems[legendItems.length - 1];
|
|
845
|
+
const endTranslateX = Number(endItem.getAttribute('data-translateX'));
|
|
846
|
+
const {
|
|
847
|
+
width: endWidth
|
|
848
|
+
} = endItem.getBoundingClientRect();
|
|
849
|
+
const offset = end - (endTranslateX + endWidth);
|
|
850
|
+
legendItems.forEach(legendItem => {
|
|
851
|
+
const curTranslateX = Number(legendItem.getAttribute('data-translateX')) + offset;
|
|
852
|
+
d3.select(legendItem).attr('transform', "translate(".concat(curTranslateX, ",0)")).attr('data-translateX', curTranslateX);
|
|
853
|
+
d3.select(legendItem).attr('opacity', 1);
|
|
854
|
+
});
|
|
855
|
+
};
|
|
571
856
|
// theta is pie or ring chart
|
|
572
857
|
this.setLegendForTheta = function (legendName) {
|
|
573
858
|
let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
|
|
@@ -581,6 +866,13 @@ class ChartComponent extends _react.Component {
|
|
|
581
866
|
basicLegendConfig.itemName.style.fontSize = theme.fontSize;
|
|
582
867
|
_this.chart.legend(legendName, basicLegendConfig);
|
|
583
868
|
};
|
|
869
|
+
this.calcEquilateralTriangle = (cx, cy, size, direction) => {
|
|
870
|
+
const height = size * Math.sqrt(3) / 2;
|
|
871
|
+
if (direction === 'bottom') {
|
|
872
|
+
return [[cx, cy + height / 2], [cx - size / 2, cy - height / 2], [cx + size / 2, cy - height / 2]];
|
|
873
|
+
}
|
|
874
|
+
return [[cx, cy - height / 2], [cx - size / 2, cy + height / 2], [cx + size / 2, cy + height / 2]];
|
|
875
|
+
};
|
|
584
876
|
this.setColorMap = (data, chartColorTheme) => {
|
|
585
877
|
let currentIdx = 0;
|
|
586
878
|
const defaultColors = _constants.CHART_STYLE_COLORS;
|
|
@@ -762,11 +1054,11 @@ class ChartComponent extends _react.Component {
|
|
|
762
1054
|
width: chartWidth
|
|
763
1055
|
} = this.chartBoundingClientRect;
|
|
764
1056
|
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 => {
|
|
1057
|
+
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
1058
|
annotationWrapper.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
|
|
767
1059
|
});
|
|
768
1060
|
};
|
|
769
|
-
this.addLabelToRectTop =
|
|
1061
|
+
this.addLabelToRectTop = _ref6 => {
|
|
770
1062
|
let {
|
|
771
1063
|
container,
|
|
772
1064
|
x,
|
|
@@ -775,7 +1067,7 @@ class ChartComponent extends _react.Component {
|
|
|
775
1067
|
theme,
|
|
776
1068
|
label_font_size,
|
|
777
1069
|
text
|
|
778
|
-
} =
|
|
1070
|
+
} = _ref6;
|
|
779
1071
|
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
1072
|
const {
|
|
781
1073
|
width
|
|
@@ -783,7 +1075,24 @@ class ChartComponent extends _react.Component {
|
|
|
783
1075
|
g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
|
|
784
1076
|
});
|
|
785
1077
|
};
|
|
786
|
-
this.
|
|
1078
|
+
this.addLabelToRectRight = _ref7 => {
|
|
1079
|
+
let {
|
|
1080
|
+
container,
|
|
1081
|
+
y,
|
|
1082
|
+
xWidth,
|
|
1083
|
+
yHeight,
|
|
1084
|
+
theme,
|
|
1085
|
+
label_font_size,
|
|
1086
|
+
text
|
|
1087
|
+
} = _ref7;
|
|
1088
|
+
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 => {
|
|
1089
|
+
const {
|
|
1090
|
+
height
|
|
1091
|
+
} = g.node().getBoundingClientRect();
|
|
1092
|
+
g.attr('y', Number(y) + Number(yHeight) / 2 - height / 2);
|
|
1093
|
+
});
|
|
1094
|
+
};
|
|
1095
|
+
this.addLabelToRectCenter = _ref8 => {
|
|
787
1096
|
let {
|
|
788
1097
|
chartType,
|
|
789
1098
|
container,
|
|
@@ -791,11 +1100,10 @@ class ChartComponent extends _react.Component {
|
|
|
791
1100
|
y,
|
|
792
1101
|
xWidth,
|
|
793
1102
|
yheight,
|
|
794
|
-
overflowHeight,
|
|
795
1103
|
theme,
|
|
796
1104
|
label_font_size,
|
|
797
1105
|
text
|
|
798
|
-
} =
|
|
1106
|
+
} = _ref8;
|
|
799
1107
|
d3.select(container).append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
|
|
800
1108
|
const {
|
|
801
1109
|
width,
|
|
@@ -804,7 +1112,7 @@ class ChartComponent extends _react.Component {
|
|
|
804
1112
|
const translateX = Number(x) + xWidth / 2 - width / 2;
|
|
805
1113
|
let translateY = Number(y) + Number(yheight / 2) + height / 2;
|
|
806
1114
|
if (chartType === _constants.CHART_TYPE.BAR_STACK) {
|
|
807
|
-
translateY = translateY
|
|
1115
|
+
translateY = translateY;
|
|
808
1116
|
}
|
|
809
1117
|
g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
|
|
810
1118
|
});
|
|
@@ -829,6 +1137,31 @@ class ChartComponent extends _react.Component {
|
|
|
829
1137
|
});
|
|
830
1138
|
}
|
|
831
1139
|
};
|
|
1140
|
+
// Use clipPath to make rectangle rounded corners
|
|
1141
|
+
this.addClipPath = _ref9 => {
|
|
1142
|
+
let {
|
|
1143
|
+
rect,
|
|
1144
|
+
parentNode,
|
|
1145
|
+
attr,
|
|
1146
|
+
rectId
|
|
1147
|
+
} = _ref9;
|
|
1148
|
+
const {
|
|
1149
|
+
borderRadius
|
|
1150
|
+
} = this.chartBoundingClientRect;
|
|
1151
|
+
const clipRect = d3.select(rect.cloneNode());
|
|
1152
|
+
if (attr === 'x') {
|
|
1153
|
+
const borderRadiusVal = Number(rect.getAttribute('height')) * borderRadius;
|
|
1154
|
+
clipRect.attr('rx', borderRadiusVal);
|
|
1155
|
+
clipRect.attr('x', Number(rect.getAttribute('x')) - borderRadiusVal).attr('width', Number(rect.getAttribute('width')) + borderRadiusVal);
|
|
1156
|
+
} else {
|
|
1157
|
+
const borderRadiusVal = Number(rect.getAttribute('width')) * borderRadius;
|
|
1158
|
+
clipRect.attr('rx', borderRadiusVal);
|
|
1159
|
+
clipRect.attr('height', Number(rect.getAttribute('height')) + borderRadiusVal);
|
|
1160
|
+
}
|
|
1161
|
+
const clipPath = d3.select(parentNode).append('clipPath').attr('id', rectId);
|
|
1162
|
+
clipPath.node().appendChild(clipRect.node());
|
|
1163
|
+
d3.select(rect).attr('clip-path', "url(#".concat(rectId, ")"));
|
|
1164
|
+
};
|
|
832
1165
|
this.initLabelStroke(props === null || props === void 0 ? void 0 : props.globalTheme);
|
|
833
1166
|
this.chartBoundingClientRect = {};
|
|
834
1167
|
}
|