@publishfx/publish-chart 2.0.2 → 2.1.0
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/CHANGELOG.md +32 -0
- package/README.md +6 -6
- package/dist/adapters/DataAdapter.d.ts +7 -3
- package/dist/adapters/DataAdapter.js +61 -0
- package/dist/components/g2/base/G2BarChart.d.ts +4 -3
- package/dist/components/g2/base/G2BarChart.js +194 -53
- package/dist/components/g2/base/G2BarLegend.d.ts +17 -0
- package/dist/components/g2/base/G2BarLegend.js +196 -0
- package/dist/components/g2/base/G2CombineChart.d.ts +9 -0
- package/dist/components/g2/base/G2CombineChart.js +305 -0
- package/dist/components/g2/base/G2GaugeChart.js +3 -1
- package/dist/components/g2/base/G2GroupBarChart.d.ts +9 -0
- package/dist/components/g2/base/G2GroupBarChart.js +227 -0
- package/dist/components/g2/base/G2IndicatorCardChart.d.ts +43 -0
- package/dist/components/g2/base/G2IndicatorCardChart.js +156 -0
- package/dist/components/g2/base/G2LineChart.d.ts +4 -3
- package/dist/components/g2/base/G2LineChart.js +207 -104
- package/dist/components/g2/base/G2PieChart.d.ts +9 -0
- package/dist/components/g2/base/G2PieChart.js +189 -0
- package/dist/components/g2/base/g2Helpers.d.ts +293 -0
- package/dist/components/g2/base/g2Helpers.js +167 -0
- package/dist/components/g2/base/g2bar.d.ts +64 -0
- package/dist/components/g2/base/g2bar.js +191 -0
- package/dist/components/g2/base/g2combine.d.ts +71 -0
- package/dist/components/g2/base/g2combine.js +322 -0
- package/dist/components/g2/base/g2groupbar.d.ts +69 -0
- package/dist/components/g2/base/g2groupbar.js +188 -0
- package/dist/components/g2/base/g2line.d.ts +77 -0
- package/dist/components/g2/base/g2line.js +208 -0
- package/dist/components/g2/shared/G2CompareTooltip.d.ts +23 -0
- package/dist/components/g2/shared/G2CompareTooltip.js +93 -0
- package/dist/components/g2/shared/useG2TooltipContainer.d.ts +1 -0
- package/dist/components/g2/shared/useG2TooltipContainer.js +16 -0
- package/dist/components/shared/NodeDetail.js +1 -1
- package/dist/components/shared/NodePopover.d.ts +1 -0
- package/dist/components/shared/NodePopover.js +3 -2
- package/dist/core/ChartTypes.d.ts +4 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -1
- package/dist/utils/chartHelpers.d.ts +1 -1
- package/dist/utils/chartHelpers.js +2 -2
- package/package.json +15 -13
|
@@ -1,150 +1,253 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useMemo, useRef } from "react";
|
|
3
|
-
import
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import react_dom from "react-dom";
|
|
4
4
|
import { useChartContext } from "../../../core/ChartContext.js";
|
|
5
|
-
import { getAxisFormat
|
|
5
|
+
import { getAxisFormat } from "../../../utils/chartHelpers.js";
|
|
6
6
|
import { DataAdapter } from "../../../adapters/DataAdapter.js";
|
|
7
|
-
|
|
7
|
+
import { NodePopover } from "../../shared/NodePopover.js";
|
|
8
|
+
import { NodeDetail } from "../../shared/NodeDetail.js";
|
|
9
|
+
import { transformIndicatorList } from "../../../utils/dataTransform.js";
|
|
10
|
+
import G2CompareTooltip from "../shared/G2CompareTooltip.js";
|
|
11
|
+
import useG2TooltipContainer from "../shared/useG2TooltipContainer.js";
|
|
12
|
+
import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
|
|
13
|
+
import { G2BarLegend } from "./G2BarLegend.js";
|
|
14
|
+
import { renderG2LineChart } from "./g2line.js";
|
|
15
|
+
const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick: _onChartClick, timeRange, legend = "", config, nodeSetting = {
|
|
8
16
|
showType: 0,
|
|
9
17
|
type: []
|
|
10
|
-
}, auxiliaryLineData })=>{
|
|
18
|
+
}, auxiliaryLineData, highlightDate, indicators = [] })=>{
|
|
19
|
+
console.log("props data: G2LineChart", data, nodeSetting, config, "x, y, z", x, y, z, "highlightDate:", highlightDate);
|
|
11
20
|
const { formatter, dataTransform, config: contextConfig } = useChartContext();
|
|
21
|
+
const tooltipContainerRef = useG2TooltipContainer();
|
|
22
|
+
const themeColors = contextConfig?.theme?.colors || [];
|
|
12
23
|
const safeIndicatorMap = indicatorMap || contextConfig.indicatorMap || {};
|
|
13
|
-
const safeLegend = legend || y;
|
|
24
|
+
const safeLegend = "groupType" !== legend ? legend || y : y;
|
|
25
|
+
const isCompare = timeRange?.compareStartTime !== "";
|
|
26
|
+
const safeY = "groupValue";
|
|
14
27
|
const chartConfig = config || {};
|
|
15
|
-
const { isDataTag = false } = chartConfig;
|
|
28
|
+
const { isDataTag = false, isHighlight = true, isLegend = true } = chartConfig;
|
|
29
|
+
const [xyList, setXYList] = useState([]);
|
|
30
|
+
const [activeIds, setActiveIds] = useState([]);
|
|
31
|
+
const [legendItems, setLegendItems] = useState([]);
|
|
32
|
+
const containerRef = useRef(null);
|
|
33
|
+
const chartRef = useRef(null);
|
|
34
|
+
const [viewWidth, setViewWidth] = useState(0);
|
|
35
|
+
const [viewOffset, setViewOffset] = useState(0);
|
|
16
36
|
const transformedData = useMemo(()=>{
|
|
17
|
-
|
|
18
|
-
|
|
37
|
+
if (!legend) {
|
|
38
|
+
let result = transformIndicatorList(indicators, data);
|
|
39
|
+
data = result[y] || [];
|
|
40
|
+
}
|
|
41
|
+
const result = DataAdapter.transform(data, "line", {
|
|
42
|
+
type: "line",
|
|
19
43
|
x,
|
|
20
|
-
y
|
|
44
|
+
y: safeY
|
|
21
45
|
});
|
|
22
46
|
return result.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap));
|
|
23
47
|
}, [
|
|
24
48
|
data,
|
|
25
49
|
x,
|
|
26
|
-
|
|
50
|
+
safeY,
|
|
27
51
|
dataTransform,
|
|
28
52
|
contextConfig.nodeMap
|
|
29
53
|
]);
|
|
30
|
-
const maxY = useMemo(()=>{
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
54
|
+
const { minY, maxY } = useMemo(()=>{
|
|
55
|
+
const dataValues = transformedData.filter((item)=>"-" !== item[safeY] && void 0 !== item[safeY] && null !== item[safeY]).map((item)=>Number(item[safeY]));
|
|
56
|
+
const compareValues = transformedData.filter((item)=>"-" !== item["subGroupValue"] && null != item["subGroupValue"]).map((item)=>Number(item["subGroupValue"]));
|
|
57
|
+
const values = [
|
|
58
|
+
...dataValues,
|
|
59
|
+
...compareValues
|
|
60
|
+
];
|
|
61
|
+
const dataMin = values.length > 0 ? Math.min(...values) : 0;
|
|
62
|
+
const dataMax = values.length > 0 ? Math.max(...values) : 0;
|
|
63
|
+
const auxValues = auxiliaryLineData?.length ? auxiliaryLineData.map((item)=>item.value) : [];
|
|
64
|
+
const minAux = auxValues.length ? Math.min(...auxValues) : dataMin;
|
|
65
|
+
const maxAux = auxValues.length ? Math.max(...auxValues) : dataMax;
|
|
66
|
+
return {
|
|
67
|
+
minY: Math.min(dataMin, minAux),
|
|
68
|
+
maxY: Math.max(dataMax, maxAux)
|
|
69
|
+
};
|
|
37
70
|
}, [
|
|
38
71
|
transformedData,
|
|
39
|
-
|
|
72
|
+
safeY,
|
|
40
73
|
auxiliaryLineData
|
|
41
74
|
]);
|
|
42
|
-
const formatAxis = (val)=>getAxisFormat(val, safeIndicatorMap, safeLegend)
|
|
43
|
-
|
|
44
|
-
|
|
75
|
+
const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, safeLegend), [
|
|
76
|
+
safeIndicatorMap,
|
|
77
|
+
safeLegend
|
|
78
|
+
]);
|
|
45
79
|
useEffect(()=>{
|
|
46
|
-
if (!
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
gridLineWidth: 2,
|
|
62
|
-
gridStrokeOpacity: 0.7,
|
|
63
|
-
gridLineDash: [
|
|
64
|
-
0,
|
|
65
|
-
0
|
|
66
|
-
],
|
|
67
|
-
labelFormatter: (val)=>formatAxis(val)
|
|
68
|
-
});
|
|
69
|
-
chart.axis('x', {
|
|
70
|
-
title: false,
|
|
71
|
-
labelAutoHide: 'greedy'
|
|
72
|
-
});
|
|
73
|
-
chart.scale({
|
|
74
|
-
y: {
|
|
75
|
-
type: 'linear',
|
|
76
|
-
domainMax: maxY,
|
|
77
|
-
nice: true
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
line.interaction('tooltip', {
|
|
81
|
-
render: (_event, { title, items })=>`<div>
|
|
82
|
-
<div>${title}</div>
|
|
83
|
-
${items?.map(({ color, name, value })=>`
|
|
84
|
-
<div style="display:flex;justify-content:space-between;line-height:12px;margin-top:5px;">
|
|
85
|
-
<div>
|
|
86
|
-
<span
|
|
87
|
-
style="display:inline-block;width:8px;height:8px;margin-right:5px;background-color:${color};border-radius:50%;"
|
|
88
|
-
></span>
|
|
89
|
-
${safeIndicatorMap[name]?.indicatorName || ''}:
|
|
90
|
-
</div>
|
|
91
|
-
<div style="padding-left:10px;font-weight:bold;">
|
|
92
|
-
${formatter.formatIndicator(value, safeIndicatorMap[name])}
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
`).join('')}
|
|
96
|
-
${auxiliaryLineData?.map(({ name, value })=>`<div
|
|
97
|
-
style="display:flex;justify-content:space-between;line-height:12px;margin-top:10px;margin-left:16px;"
|
|
98
|
-
>
|
|
99
|
-
<div style="margin-right:8px">${name}:</div>
|
|
100
|
-
<div>${formatter.formatIndicator(value, safeIndicatorMap[safeLegend])}</div>
|
|
101
|
-
</div>`).join('')}
|
|
102
|
-
</div>`
|
|
80
|
+
if (!transformedData.length) {
|
|
81
|
+
setLegendItems([]);
|
|
82
|
+
setActiveIds([]);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const groupTypes = Array.from(new Set(transformedData.map((d)=>d.groupType).filter((v)=>null != v)));
|
|
86
|
+
const items = groupTypes.map((id, index)=>{
|
|
87
|
+
const colorIndex = isCompare ? Math.floor(index / 2) : index;
|
|
88
|
+
return {
|
|
89
|
+
id: String(id),
|
|
90
|
+
label: getIndicatorCompareName(safeIndicatorMap, String(id)) + (id.includes("_compare") ? `(对比时间:${timeRange?.compareStartTime}~${timeRange?.compareEndTime})` : ""),
|
|
91
|
+
color: themeColors[colorIndex % themeColors.length] ?? themeColors[0] ?? "#5B8FF9",
|
|
92
|
+
isCompare: String(id).includes("_compare"),
|
|
93
|
+
symbol: "line"
|
|
94
|
+
};
|
|
103
95
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
96
|
+
setLegendItems(items);
|
|
97
|
+
if (!activeIds.length) setActiveIds(items.map((i)=>i.id));
|
|
98
|
+
}, [
|
|
99
|
+
transformedData,
|
|
100
|
+
safeIndicatorMap,
|
|
101
|
+
themeColors,
|
|
102
|
+
activeIds.length
|
|
103
|
+
]);
|
|
104
|
+
const filteredData = useMemo(()=>{
|
|
105
|
+
if (!activeIds.length) return transformedData;
|
|
106
|
+
return transformedData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType)) : true);
|
|
107
|
+
}, [
|
|
108
|
+
transformedData,
|
|
109
|
+
activeIds
|
|
110
|
+
]);
|
|
111
|
+
const canvasMarginBottom = legendItems.length > 1 ? 2 === nodeSetting.showType ? 32 : 16 : 0;
|
|
112
|
+
useEffect(()=>{
|
|
113
|
+
if (!containerRef.current || !filteredData.length) return;
|
|
114
|
+
if (chartRef.current) {
|
|
115
|
+
chartRef.current.destroy();
|
|
116
|
+
chartRef.current = null;
|
|
117
|
+
}
|
|
118
|
+
console.log("G2LineChart", x, y, minY, maxY);
|
|
119
|
+
const chart = renderG2LineChart(containerRef.current, {
|
|
120
|
+
data: filteredData,
|
|
121
|
+
x,
|
|
122
|
+
y: safeY,
|
|
123
|
+
minY,
|
|
124
|
+
maxY,
|
|
125
|
+
themeColors,
|
|
126
|
+
indicators,
|
|
127
|
+
indicatorMap: safeIndicatorMap,
|
|
128
|
+
formatAxis,
|
|
129
|
+
highlightDate: highlightDate ?? [],
|
|
130
|
+
auxiliaryLineData: auxiliaryLineData ?? [],
|
|
131
|
+
isDataTag,
|
|
132
|
+
isLegend: !!isCompare,
|
|
133
|
+
isHighlight,
|
|
134
|
+
timeRange,
|
|
135
|
+
formatLabel: isDataTag ? (d)=>{
|
|
136
|
+
const indicatorId = d.groupType.split("_")[0];
|
|
137
|
+
return "-" === formatter.formatIndicator(d.groupValue, safeIndicatorMap[indicatorId]) ? "" : formatter.formatIndicator(d.groupValue, safeIndicatorMap[indicatorId]);
|
|
138
|
+
} : void 0,
|
|
139
|
+
height: height - canvasMarginBottom,
|
|
140
|
+
tooltipRender: (title, items)=>{
|
|
141
|
+
const container = tooltipContainerRef.current;
|
|
142
|
+
if (!container) return null;
|
|
143
|
+
let safeItems = items.map((i)=>({
|
|
144
|
+
...i,
|
|
145
|
+
color: i.color ?? themeColors[0] ?? "#5B8FF9"
|
|
146
|
+
}));
|
|
147
|
+
console.log("safeItems:", safeItems);
|
|
148
|
+
react_dom.render(/*#__PURE__*/ jsx(G2CompareTooltip, {
|
|
149
|
+
title: title,
|
|
150
|
+
items: safeItems,
|
|
151
|
+
safeIndicatorMap: safeIndicatorMap,
|
|
152
|
+
formatter: formatter,
|
|
153
|
+
safeLegend: safeLegend,
|
|
154
|
+
auxiliaryLineData: auxiliaryLineData
|
|
155
|
+
}), container);
|
|
156
|
+
return container;
|
|
157
|
+
},
|
|
158
|
+
legendSize: 12,
|
|
159
|
+
useStrictTicks: true,
|
|
160
|
+
onNodeListChange: (nodes)=>{
|
|
161
|
+
setXYList(nodes);
|
|
162
|
+
},
|
|
163
|
+
onChartRender: (chartProps)=>{
|
|
164
|
+
const layout = chartProps?.layout;
|
|
165
|
+
if (layout) {
|
|
166
|
+
setViewWidth(layout.innerWidth ?? 0);
|
|
167
|
+
setViewOffset((layout.paddingLeft ?? 0) + (layout.marginLeft ?? 0));
|
|
111
168
|
}
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
if (isDataTag) line.label({
|
|
115
|
-
text: (d)=>formatter.formatIndicator(d[y], safeIndicatorMap[y])
|
|
169
|
+
}
|
|
116
170
|
});
|
|
117
|
-
chart.render();
|
|
118
171
|
chartRef.current = chart;
|
|
119
172
|
return ()=>{
|
|
120
173
|
if (chartRef.current) {
|
|
121
|
-
chartRef.current.off(
|
|
122
|
-
chartRef.current.off(
|
|
123
|
-
chartRef.current.off(
|
|
174
|
+
chartRef.current.off("element:click");
|
|
175
|
+
chartRef.current.off("element:mouseenter");
|
|
176
|
+
chartRef.current.off("element:mouseleave");
|
|
124
177
|
chartRef.current.destroy();
|
|
125
178
|
chartRef.current = null;
|
|
126
179
|
}
|
|
127
180
|
};
|
|
128
181
|
}, [
|
|
129
|
-
|
|
182
|
+
filteredData,
|
|
130
183
|
height,
|
|
131
184
|
x,
|
|
132
185
|
y,
|
|
133
186
|
safeLegend,
|
|
134
187
|
isDataTag,
|
|
188
|
+
isLegend,
|
|
189
|
+
isHighlight,
|
|
135
190
|
maxY,
|
|
136
191
|
safeIndicatorMap,
|
|
137
192
|
formatter,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
193
|
+
formatAxis,
|
|
194
|
+
highlightDate,
|
|
195
|
+
auxiliaryLineData,
|
|
196
|
+
themeColors
|
|
141
197
|
]);
|
|
142
|
-
|
|
143
|
-
|
|
198
|
+
console.log("legendItems:", legendItems);
|
|
199
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
144
200
|
style: {
|
|
145
|
-
width:
|
|
146
|
-
|
|
147
|
-
}
|
|
201
|
+
width: "100%",
|
|
202
|
+
position: "relative"
|
|
203
|
+
},
|
|
204
|
+
children: [
|
|
205
|
+
isLegend && legendItems.length > 1 && 2 === nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
206
|
+
items: legendItems,
|
|
207
|
+
activeIds: activeIds,
|
|
208
|
+
onChange: setActiveIds,
|
|
209
|
+
style: {
|
|
210
|
+
marginBottom: 8
|
|
211
|
+
}
|
|
212
|
+
}),
|
|
213
|
+
/*#__PURE__*/ jsx("div", {
|
|
214
|
+
ref: containerRef,
|
|
215
|
+
style: {
|
|
216
|
+
width: "100%",
|
|
217
|
+
height: `${height - canvasMarginBottom}px`
|
|
218
|
+
}
|
|
219
|
+
}),
|
|
220
|
+
isLegend && legendItems.length > 1 && 2 !== nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
221
|
+
items: legendItems,
|
|
222
|
+
activeIds: activeIds,
|
|
223
|
+
onChange: setActiveIds,
|
|
224
|
+
style: {
|
|
225
|
+
marginBottom: 8
|
|
226
|
+
}
|
|
227
|
+
}),
|
|
228
|
+
2 !== nodeSetting.showType ? /*#__PURE__*/ jsx("div", {
|
|
229
|
+
children: xyList?.map((item, index)=>/*#__PURE__*/ jsx(NodePopover, {
|
|
230
|
+
style: {
|
|
231
|
+
position: "absolute",
|
|
232
|
+
top: item.pointP?.y + 10,
|
|
233
|
+
left: item.pointP?.x,
|
|
234
|
+
width: 12,
|
|
235
|
+
height: 12,
|
|
236
|
+
borderRadius: "50%",
|
|
237
|
+
transform: "translate(-50%, 0%)",
|
|
238
|
+
background: item?.color,
|
|
239
|
+
zIndex: 999
|
|
240
|
+
},
|
|
241
|
+
pointP: item.pointP,
|
|
242
|
+
pointData: item.pointData
|
|
243
|
+
}, index))
|
|
244
|
+
}) : /*#__PURE__*/ jsx(NodeDetail, {
|
|
245
|
+
chartWidth: viewWidth,
|
|
246
|
+
chartOffset: viewOffset,
|
|
247
|
+
dvRows: transformedData,
|
|
248
|
+
ratio: timeRange?.compareStartTime !== "" ? 2 : 1
|
|
249
|
+
})
|
|
250
|
+
]
|
|
148
251
|
});
|
|
149
252
|
};
|
|
150
253
|
const base_G2LineChart = G2LineChart;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* G2@5 基础饼图组件
|
|
3
|
+
* 使用 G2@5 的 interval API 实现饼图
|
|
4
|
+
*/
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import type { BaseChartProps } from '../../../core/ChartTypes';
|
|
7
|
+
export declare const newThemeColors: string[];
|
|
8
|
+
declare const G2PieChart: React.FC<BaseChartProps>;
|
|
9
|
+
export default G2PieChart;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
3
|
+
import { Chart } from "@antv/g2";
|
|
4
|
+
import { useChartContext } from "../../../core/ChartContext.js";
|
|
5
|
+
import { DataAdapter } from "../../../adapters/DataAdapter.js";
|
|
6
|
+
const newThemeColors = [
|
|
7
|
+
'#5B8FF9',
|
|
8
|
+
'#5AD8A6',
|
|
9
|
+
'#5D7092',
|
|
10
|
+
'#F6BD16',
|
|
11
|
+
'#6F5EF9',
|
|
12
|
+
'#6DC8EC',
|
|
13
|
+
'#945FB9',
|
|
14
|
+
'#FF9845',
|
|
15
|
+
'#1E9493',
|
|
16
|
+
'#FF99C3',
|
|
17
|
+
'#8CD85A',
|
|
18
|
+
'#FE765E',
|
|
19
|
+
'#67A1FF',
|
|
20
|
+
'#D85ACB',
|
|
21
|
+
'#F95B8F'
|
|
22
|
+
];
|
|
23
|
+
const G2PieChart = ({ height = 400, data, x = '', y = '', indicatorMap, onChartClick, config })=>{
|
|
24
|
+
const { formatter, dataTransform, config: contextConfig } = useChartContext();
|
|
25
|
+
const safeIndicatorMap = indicatorMap || contextConfig.indicatorMap || {};
|
|
26
|
+
const chartConfig = config || {};
|
|
27
|
+
const { innerRadius = 0.6, outerRadius = 0.7, minLabelPercentage = 3 } = chartConfig || {};
|
|
28
|
+
const transformedData = useMemo(()=>{
|
|
29
|
+
if (!data || 0 === data.length) return [];
|
|
30
|
+
const result = DataAdapter.transform(data, 'line', {
|
|
31
|
+
type: 'line',
|
|
32
|
+
x,
|
|
33
|
+
y
|
|
34
|
+
});
|
|
35
|
+
return result.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap)).filter((item)=>{
|
|
36
|
+
const value = item[y];
|
|
37
|
+
return '-' !== value && null != value && !isNaN(Number(value));
|
|
38
|
+
});
|
|
39
|
+
}, [
|
|
40
|
+
data,
|
|
41
|
+
x,
|
|
42
|
+
y,
|
|
43
|
+
dataTransform,
|
|
44
|
+
contextConfig.nodeMap
|
|
45
|
+
]);
|
|
46
|
+
const totalValue = useMemo(()=>transformedData.reduce((sum, item)=>{
|
|
47
|
+
const value = Number(item[y]) || 0;
|
|
48
|
+
return sum + value;
|
|
49
|
+
}, 0), [
|
|
50
|
+
transformedData,
|
|
51
|
+
y
|
|
52
|
+
]);
|
|
53
|
+
const containerRef = useRef(null);
|
|
54
|
+
const chartRef = useRef(null);
|
|
55
|
+
const centerTextRef = useRef(null);
|
|
56
|
+
useEffect(()=>{
|
|
57
|
+
if (!containerRef.current || !transformedData.length) return;
|
|
58
|
+
if (chartRef.current) chartRef.current.destroy();
|
|
59
|
+
if (centerTextRef.current && centerTextRef.current.parentNode) centerTextRef.current.parentNode.removeChild(centerTextRef.current);
|
|
60
|
+
const chart = new Chart({
|
|
61
|
+
container: containerRef.current,
|
|
62
|
+
autoFit: true,
|
|
63
|
+
height: height
|
|
64
|
+
});
|
|
65
|
+
if (containerRef.current) containerRef.current.style.position = 'relative';
|
|
66
|
+
chart.data(transformedData);
|
|
67
|
+
chart.coordinate({
|
|
68
|
+
type: 'theta',
|
|
69
|
+
innerRadius: innerRadius,
|
|
70
|
+
outerRadius: outerRadius,
|
|
71
|
+
startAngle: -Math.PI / 2
|
|
72
|
+
});
|
|
73
|
+
chart.scale({
|
|
74
|
+
[y]: {
|
|
75
|
+
nice: true
|
|
76
|
+
},
|
|
77
|
+
[x]: {
|
|
78
|
+
type: 'cat'
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
chart.legend('color', {
|
|
82
|
+
position: 'bottom',
|
|
83
|
+
itemHeight: 14,
|
|
84
|
+
maxItemWidth: 1,
|
|
85
|
+
gridRow: 1
|
|
86
|
+
});
|
|
87
|
+
chart.interaction('poptip', true);
|
|
88
|
+
const interval = chart.interval().encode('y', y).encode('color', x).scale('color', {
|
|
89
|
+
type: 'ordinal',
|
|
90
|
+
range: newThemeColors
|
|
91
|
+
}).transform({
|
|
92
|
+
type: 'stackY'
|
|
93
|
+
});
|
|
94
|
+
const currentTotalValue = totalValue;
|
|
95
|
+
interval.label({
|
|
96
|
+
text: (d)=>{
|
|
97
|
+
const value = Number(d[y]) || 0;
|
|
98
|
+
const percentage = currentTotalValue > 0 ? value / currentTotalValue * 100 : 0;
|
|
99
|
+
const percentageStr = percentage.toFixed(2);
|
|
100
|
+
const indicatorInfo = safeIndicatorMap[y];
|
|
101
|
+
const formattedValue = formatter.formatIndicator(value, indicatorInfo);
|
|
102
|
+
const categoryName = safeIndicatorMap[d[x]]?.indicatorName || d[x] || '';
|
|
103
|
+
const maxCategoryLength = percentage >= 10 ? 20 : percentage >= 5 ? 15 : 12;
|
|
104
|
+
const truncatedCategory = categoryName.length > maxCategoryLength ? categoryName.substring(0, maxCategoryLength - 3) + '...' : categoryName;
|
|
105
|
+
return `${percentageStr}%(${formattedValue})\n${truncatedCategory}`;
|
|
106
|
+
},
|
|
107
|
+
position: 'spider',
|
|
108
|
+
offset: 20,
|
|
109
|
+
connector: true,
|
|
110
|
+
connectorDistance: 0,
|
|
111
|
+
labelHeight: 32,
|
|
112
|
+
connectorStroke: (_d, index)=>{
|
|
113
|
+
const color = newThemeColors[index];
|
|
114
|
+
return color;
|
|
115
|
+
},
|
|
116
|
+
fontSize: (d, _index)=>{
|
|
117
|
+
const value = Number(d[y]) || 0;
|
|
118
|
+
const percentage = currentTotalValue > 0 ? value / currentTotalValue * 100 : 0;
|
|
119
|
+
if (percentage >= 10) return 12;
|
|
120
|
+
return 12;
|
|
121
|
+
},
|
|
122
|
+
transform: [
|
|
123
|
+
{
|
|
124
|
+
type: 'dodgeY'
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
chart.render();
|
|
129
|
+
const visibleTotalValue = transformedData.reduce((sum, item)=>{
|
|
130
|
+
const value = Number(item[y]) || 0;
|
|
131
|
+
return sum + value;
|
|
132
|
+
}, 0);
|
|
133
|
+
const indicatorInfo = safeIndicatorMap[y];
|
|
134
|
+
const formattedTotal = formatter.formatIndicator(visibleTotalValue, indicatorInfo);
|
|
135
|
+
const centerTextContainer = document.createElement('div');
|
|
136
|
+
centerTextContainer.style.position = 'absolute';
|
|
137
|
+
centerTextContainer.style.left = '50%';
|
|
138
|
+
centerTextContainer.style.top = '50%';
|
|
139
|
+
centerTextContainer.style.transform = 'translate(-50%, -50%)';
|
|
140
|
+
centerTextContainer.style.textAlign = 'center';
|
|
141
|
+
centerTextContainer.style.pointerEvents = 'none';
|
|
142
|
+
const totalLabelEl = document.createElement('div');
|
|
143
|
+
totalLabelEl.textContent = 'total';
|
|
144
|
+
totalLabelEl.style.fontSize = '14px';
|
|
145
|
+
totalLabelEl.style.color = '#86909c';
|
|
146
|
+
totalLabelEl.style.marginBottom = '5px';
|
|
147
|
+
const totalValueEl = document.createElement('div');
|
|
148
|
+
totalValueEl.textContent = formattedTotal;
|
|
149
|
+
totalValueEl.style.fontSize = '20px';
|
|
150
|
+
totalValueEl.style.color = '#1d2129';
|
|
151
|
+
totalValueEl.style.fontWeight = 'bold';
|
|
152
|
+
centerTextContainer.appendChild(totalLabelEl);
|
|
153
|
+
centerTextContainer.appendChild(totalValueEl);
|
|
154
|
+
containerRef.current?.appendChild(centerTextContainer);
|
|
155
|
+
centerTextRef.current = centerTextContainer;
|
|
156
|
+
chartRef.current = chart;
|
|
157
|
+
if (onChartClick) chart.on('element:click', (e)=>{
|
|
158
|
+
const data = e.data?.data;
|
|
159
|
+
if (data) onChartClick(data);
|
|
160
|
+
});
|
|
161
|
+
return ()=>{
|
|
162
|
+
if (chartRef.current) {
|
|
163
|
+
chartRef.current.destroy();
|
|
164
|
+
chartRef.current = null;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}, [
|
|
168
|
+
transformedData,
|
|
169
|
+
height,
|
|
170
|
+
x,
|
|
171
|
+
y,
|
|
172
|
+
innerRadius,
|
|
173
|
+
outerRadius,
|
|
174
|
+
minLabelPercentage,
|
|
175
|
+
totalValue,
|
|
176
|
+
safeIndicatorMap,
|
|
177
|
+
formatter,
|
|
178
|
+
onChartClick
|
|
179
|
+
]);
|
|
180
|
+
return /*#__PURE__*/ jsx("div", {
|
|
181
|
+
ref: containerRef,
|
|
182
|
+
style: {
|
|
183
|
+
width: '100%',
|
|
184
|
+
height: `${height}px`
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
const base_G2PieChart = G2PieChart;
|
|
189
|
+
export { base_G2PieChart as default, newThemeColors };
|