@publishfx/publish-chart 2.1.3 → 2.1.5
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 +16 -0
- package/dist/adapters/DataAdapter.d.ts +2 -5
- package/dist/adapters/DataAdapter.js +24 -52
- package/dist/components/g2/base/G2BarChart.js +8 -3
- package/dist/components/g2/base/G2BarLegend.js +1 -2
- package/dist/components/g2/base/G2CombineChart.js +81 -55
- package/dist/components/g2/base/G2LineChart.js +17 -6
- package/dist/components/g2/base/g2Helpers.d.ts +3 -0
- package/dist/components/g2/base/g2Helpers.js +22 -11
- package/dist/components/g2/base/g2bar.d.ts +2 -0
- package/dist/components/g2/base/g2bar.js +10 -8
- package/dist/components/g2/base/g2combine.d.ts +7 -0
- package/dist/components/g2/base/g2combine.js +86 -64
- package/dist/components/g2/base/g2line.js +6 -2
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
**2.1.5** fix(chart): 修正ts错误
|
|
2
|
+
- 2026-03-03T04:41:18+08:00 [fix(chart): 修正ts错误](http://lf.git.oa.mt/publish_platform/web/publish/commit/ed6bc3403d6c06d8c0cce6f0193a447d74b68a3a)
|
|
3
|
+
- 2026-03-03T04:38:12+08:00 [fix(chart): 组合图代码整理](http://lf.git.oa.mt/publish_platform/web/publish/commit/6a94afb106447e54143f4a29e7d8fa24c718b321)
|
|
4
|
+
- 2026-03-03T01:44:41+08:00 [fix(chart): 修复一些问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/52b05bffc199010d0ed76c112f615937c33edc53)
|
|
5
|
+
- 2026-03-03T00:19:14+08:00 [fix(chart): 辅助线不显示y轴](http://lf.git.oa.mt/publish_platform/web/publish/commit/4a7de7122d0ec4f037b95927f93a2626e7a8837a)
|
|
6
|
+
- 2026-03-03T00:13:56+08:00 [fix: 修复一批组合图和折线图的BUG](http://lf.git.oa.mt/publish_platform/web/publish/commit/c9f3f2a758ae49c94dada96acb859e8e842877ea)
|
|
7
|
+
- 2026-03-02T21:49:02+08:00 [feat(chart): 组合图排序](http://lf.git.oa.mt/publish_platform/web/publish/commit/46000898aac62b20b9c4f1543a0437808e795021)
|
|
8
|
+
- 2026-03-02T20:35:15+08:00 [fix: [f-6849783906] 修复柱状图倒序问题及图例编辑时不展示问题](http://lf.git.oa.mt/publish_platform/web/publish/commit/5fc94ba48503403c2aee24d59fc9ad6e71ce3a2d)
|
|
9
|
+
- 2026-03-02T20:24:49+08:00 [feat(chart): 组合图数据标签](http://lf.git.oa.mt/publish_platform/web/publish/commit/ec86c8ef7479f60c19d9a817212b2b3290a9c00f)
|
|
10
|
+
- 2026-03-02T19:37:12+08:00 [feat: 组合图辅助线](http://lf.git.oa.mt/publish_platform/web/publish/commit/7ea103172eb0f2529bd067a4187c4f9d6387dd0f)
|
|
11
|
+
- 2026-03-02T19:06:57+08:00 [feat(chart): 组合图折线逻辑](http://lf.git.oa.mt/publish_platform/web/publish/commit/c13e0dbf072b4736742a84890394a923495a6c54)
|
|
12
|
+
|
|
13
|
+
**2.1.4** feat(chart): 柱状、折线、组合三个图表支持onChartClick
|
|
14
|
+
- 2026-03-02T15:27:33+08:00 [feat(chart): 柱状、折线、组合三个图表支持onChartClick](http://lf.git.oa.mt/publish_platform/web/publish/commit/0cbed83b537a5b0a08f676256b8e69bb9ae0741a)
|
|
15
|
+
- 2026-03-02T14:38:28+08:00 [fix(chart): 组合图针对副轴数据全为0时,Y刻度的处理。](http://lf.git.oa.mt/publish_platform/web/publish/commit/2b262810e33d3660255831fb7ef0e345907841e9)
|
|
16
|
+
|
|
1
17
|
**2.1.3** fix(chart): 组合图分组时inset置为0
|
|
2
18
|
- 2026-02-28T23:48:20+08:00 [fix(chart): 组合图分组时inset置为0](http://lf.git.oa.mt/publish_platform/web/publish/commit/047e02d3cfbce21101277f48e904864163b2a02c)
|
|
3
19
|
- 2026-02-28T22:42:20+08:00 [feat(chart): 组合图tooltip数据调整](http://lf.git.oa.mt/publish_platform/web/publish/commit/f79461050699b0755c8837e26b035083ec980cf1)
|
|
@@ -5,6 +5,7 @@ export interface TransformConfig {
|
|
|
5
5
|
z?: string;
|
|
6
6
|
isDescend?: boolean;
|
|
7
7
|
isHorizontal?: boolean;
|
|
8
|
+
isGroup?: boolean;
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* 数据适配器类
|
|
@@ -13,7 +14,7 @@ export declare class DataAdapter {
|
|
|
13
14
|
/**
|
|
14
15
|
* 统一的数据转换接口
|
|
15
16
|
*/
|
|
16
|
-
static transform(data: any[], transformType: TransformConfig['type'], config: TransformConfig): any
|
|
17
|
+
static transform(data: any[], transformType: TransformConfig['type'], config: TransformConfig): any;
|
|
17
18
|
/**
|
|
18
19
|
* 柱状图数据转换
|
|
19
20
|
*/
|
|
@@ -30,10 +31,6 @@ export declare class DataAdapter {
|
|
|
30
31
|
* 柱状折线组合图数据转换
|
|
31
32
|
*/
|
|
32
33
|
private static transformForBarLine;
|
|
33
|
-
/**
|
|
34
|
-
* 分组柱状折线组合图数据转换
|
|
35
|
-
*/
|
|
36
|
-
private static transformForGroupBarLine;
|
|
37
34
|
/**
|
|
38
35
|
* 分组对比图数据转换
|
|
39
36
|
*/
|
|
@@ -11,8 +11,6 @@ class DataAdapter {
|
|
|
11
11
|
return this.transformForLine(data, config);
|
|
12
12
|
case 'barLine':
|
|
13
13
|
return this.transformForBarLine(data, config);
|
|
14
|
-
case 'groupBarLine':
|
|
15
|
-
return this.transformForGroupBarLine(data, config);
|
|
16
14
|
case 'groupCompare':
|
|
17
15
|
return this.transformForGroupCompare(data, config);
|
|
18
16
|
default:
|
|
@@ -30,14 +28,16 @@ class DataAdapter {
|
|
|
30
28
|
return row;
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
|
-
if (config.isDescend)
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
if (config.isDescend) {
|
|
32
|
+
const compareData = dv.rows.filter((row)=>String(row.groupType ?? '').includes('_compare'));
|
|
33
|
+
const basicData = dv.rows.filter((row)=>!String(row.groupType ?? '').includes('_compare'));
|
|
34
|
+
basicData.sort((a, b)=>{
|
|
36
35
|
if ('-' === a[config.y]) return config.isHorizontal ? -1 : 1;
|
|
37
36
|
if ('-' === b[config.y]) return config.isHorizontal ? 1 : -1;
|
|
38
|
-
return b[config.y] - a[config.y];
|
|
39
|
-
}
|
|
40
|
-
|
|
37
|
+
return config.isHorizontal ? a[config.y] - b[config.y] : b[config.y] - a[config.y];
|
|
38
|
+
});
|
|
39
|
+
dv.rows = basicData.concat(compareData);
|
|
40
|
+
}
|
|
41
41
|
}
|
|
42
42
|
return dv.rows;
|
|
43
43
|
}
|
|
@@ -113,28 +113,10 @@ class DataAdapter {
|
|
|
113
113
|
return dv.rows;
|
|
114
114
|
}
|
|
115
115
|
static transformForBarLine(data, config) {
|
|
116
|
-
const ds = new lib();
|
|
117
|
-
const dv = ds.createView().source(data);
|
|
118
|
-
if (config.y) dv.transform({
|
|
119
|
-
type: 'map',
|
|
120
|
-
callback: (row)=>{
|
|
121
|
-
row[config.y] = '' !== row[config.y] ? +row[config.y] : '-';
|
|
122
|
-
return row;
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
if (config.z) dv.transform({
|
|
126
|
-
type: 'map',
|
|
127
|
-
callback: (row)=>{
|
|
128
|
-
row[config.z] = '' !== row[config.z] ? +row[config.z] : '-';
|
|
129
|
-
return row;
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
return dv.rows;
|
|
133
|
-
}
|
|
134
|
-
static transformForGroupBarLine(data, config) {
|
|
135
116
|
const ds = new lib();
|
|
136
117
|
const dv = ds.createView().source(data);
|
|
137
118
|
const tdv = ds.createView().source(data);
|
|
119
|
+
const combinedv = ds.createView().source(data);
|
|
138
120
|
if (config.y && config.x) {
|
|
139
121
|
dv.transform({
|
|
140
122
|
type: 'map',
|
|
@@ -156,28 +138,19 @@ class DataAdapter {
|
|
|
156
138
|
return !row.isCombine;
|
|
157
139
|
}
|
|
158
140
|
});
|
|
159
|
-
|
|
141
|
+
combinedv.transform({
|
|
160
142
|
type: 'filter',
|
|
161
143
|
callback (row) {
|
|
162
|
-
return
|
|
144
|
+
return row.isCombine;
|
|
163
145
|
}
|
|
164
146
|
});
|
|
165
147
|
tdv.transform({
|
|
166
|
-
type: '
|
|
167
|
-
|
|
168
|
-
config.y
|
|
169
|
-
|
|
170
|
-
groupBy: [
|
|
171
|
-
config.x
|
|
172
|
-
],
|
|
173
|
-
operations: [
|
|
174
|
-
'sum'
|
|
175
|
-
],
|
|
176
|
-
as: [
|
|
177
|
-
'total'
|
|
178
|
-
]
|
|
148
|
+
type: 'filter',
|
|
149
|
+
callback (row) {
|
|
150
|
+
return !row[config.y] || '-' !== row[config.y];
|
|
151
|
+
}
|
|
179
152
|
});
|
|
180
|
-
tdv.transform({
|
|
153
|
+
if (config.isDescend) tdv.transform({
|
|
181
154
|
type: 'sort',
|
|
182
155
|
callback (a, b) {
|
|
183
156
|
return b.total - a.total;
|
|
@@ -185,16 +158,15 @@ class DataAdapter {
|
|
|
185
158
|
});
|
|
186
159
|
const xKey = config.x ?? 'x';
|
|
187
160
|
const sortData = tdv.rows.map((item)=>item[xKey]);
|
|
188
|
-
if (config.isDescend)
|
|
189
|
-
|
|
190
|
-
callback (a, b) {
|
|
191
|
-
if (-1 === sortData.indexOf(a[xKey])) return 1;
|
|
192
|
-
if (-1 === sortData.indexOf(b[xKey])) return -1;
|
|
193
|
-
return sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
161
|
+
if (config.isDescend) combinedv.rows.sort((a, b)=>sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]));
|
|
162
|
+
else combinedv.rows.sort((a, b)=>sortData.indexOf(a[xKey]) - sortData.indexOf(b[xKey]));
|
|
196
163
|
}
|
|
197
|
-
|
|
164
|
+
console.log('renderG2CombineChart transformedData:leftData:', tdv.rows, 'rightData:', combinedv.rows);
|
|
165
|
+
return {
|
|
166
|
+
transformedData: dv.rows,
|
|
167
|
+
leftData: tdv.rows,
|
|
168
|
+
rightData: combinedv.rows
|
|
169
|
+
};
|
|
198
170
|
}
|
|
199
171
|
static transformForGroupCompare(data, _config) {
|
|
200
172
|
return data;
|
|
@@ -122,6 +122,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
|
|
|
122
122
|
isLegend: !!isCompare,
|
|
123
123
|
isHorizontal,
|
|
124
124
|
isHighlight,
|
|
125
|
+
isClickable: !!onChartClick,
|
|
125
126
|
legend: safeLegend || void 0,
|
|
126
127
|
formatLabel: isDataTag && safeY ? (d)=>{
|
|
127
128
|
const v = d[safeY];
|
|
@@ -160,8 +161,11 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
|
|
|
160
161
|
});
|
|
161
162
|
chartRef.current = chart;
|
|
162
163
|
if (onChartClick) chart.on("element:click", (e)=>{
|
|
164
|
+
console.log('e:', e);
|
|
163
165
|
const datum = e.data?.data;
|
|
164
|
-
if (datum) onChartClick(
|
|
166
|
+
if (datum) onChartClick({
|
|
167
|
+
title: datum[x]
|
|
168
|
+
});
|
|
165
169
|
});
|
|
166
170
|
return ()=>{
|
|
167
171
|
if (chartRef.current) {
|
|
@@ -180,6 +184,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
|
|
|
180
184
|
isDataTag,
|
|
181
185
|
isLegend,
|
|
182
186
|
isHighlight,
|
|
187
|
+
isCompare,
|
|
183
188
|
maxY,
|
|
184
189
|
themeColors,
|
|
185
190
|
safeIndicatorMap,
|
|
@@ -196,7 +201,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
|
|
|
196
201
|
position: "relative"
|
|
197
202
|
},
|
|
198
203
|
children: [
|
|
199
|
-
isLegend && legendItems.length > 1 && 2 === nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
204
|
+
(isLegend || isCompare) && legendItems.length > 1 && 2 === nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
200
205
|
items: legendItems,
|
|
201
206
|
activeIds: activeIds,
|
|
202
207
|
onChange: setActiveIds,
|
|
@@ -211,7 +216,7 @@ const G2BarChart = ({ height = 300, data, x = "", y = "", indicatorMap, onChartC
|
|
|
211
216
|
height: `${height - canvasMarginBottom}px`
|
|
212
217
|
}
|
|
213
218
|
}),
|
|
214
|
-
isLegend && legendItems.length > 1 && 2 !== nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
219
|
+
(isLegend || isCompare) && legendItems.length > 1 && 2 !== nodeSetting.showType && /*#__PURE__*/ jsx(G2BarLegend, {
|
|
215
220
|
items: legendItems,
|
|
216
221
|
activeIds: activeIds,
|
|
217
222
|
onChange: setActiveIds,
|
|
@@ -17,14 +17,12 @@ const G2BarLegend = ({ items, activeIds, onChange, pageSize: pageSizeProp, maxLa
|
|
|
17
17
|
const availableWidth = Math.max(0, width - pagerReserveWidth);
|
|
18
18
|
const estimatedItemWidths = items.map((item)=>{
|
|
19
19
|
const labelLength = item.label ? item.label.length : 0;
|
|
20
|
-
console.log("computePageSize: estimatedItemWidths:", item.label, labelLength);
|
|
21
20
|
const visibleChars = labelLength;
|
|
22
21
|
return 16 + 8 * visibleChars;
|
|
23
22
|
});
|
|
24
23
|
const avgItemWidth = estimatedItemWidths.reduce((sum, w)=>sum + w, 0) / estimatedItemWidths.length;
|
|
25
24
|
if (!avgItemWidth || !isFinite(avgItemWidth)) return void setAutoPageSize(items.length || 1);
|
|
26
25
|
const computed = Math.max(1, Math.floor(availableWidth / avgItemWidth));
|
|
27
|
-
console.log("computePageSize: computed:", computed, availableWidth, avgItemWidth, estimatedItemWidths);
|
|
28
26
|
setAutoPageSize(computed);
|
|
29
27
|
setPage((p)=>Math.min(p, Math.max(1, Math.ceil(items.length / computed))));
|
|
30
28
|
};
|
|
@@ -51,6 +49,7 @@ const G2BarLegend = ({ items, activeIds, onChange, pageSize: pageSizeProp, maxLa
|
|
|
51
49
|
]);
|
|
52
50
|
const handleToggle = (id)=>{
|
|
53
51
|
const isActive = activeIds.includes(id);
|
|
52
|
+
if (isActive && activeIds.length <= 1) return;
|
|
54
53
|
const nextSet = new Set(isActive ? activeIds.filter((x)=>x !== id) : [
|
|
55
54
|
...activeIds,
|
|
56
55
|
id
|
|
@@ -63,68 +63,65 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
63
63
|
}, indicators = [], auxiliaryLineData, highlightDate, timeRange, isGroup })=>{
|
|
64
64
|
const { formatter, dataTransform, config: contextConfig } = useChartContext();
|
|
65
65
|
const tooltipContainerRef = useG2TooltipContainer();
|
|
66
|
+
const isGroupRef = useRef(isGroup);
|
|
67
|
+
const [isOldData, setIsOldData] = useState(false);
|
|
68
|
+
isGroupRef.current = isGroup;
|
|
66
69
|
console.log("G2CombineChart props:", data, x, y, z, indicators, legend, config, nodeSetting);
|
|
67
70
|
const themeColors = contextConfig?.theme?.colors || [];
|
|
68
71
|
const safeIndicatorMap = indicatorMap || contextConfig.indicatorMap || {};
|
|
69
|
-
const safeLegend =
|
|
70
|
-
if (isGroup) return legend || 'groupType';
|
|
71
|
-
if ("groupType" === legend) return y;
|
|
72
|
-
return legend || y;
|
|
73
|
-
}, [
|
|
74
|
-
isGroup,
|
|
75
|
-
legend,
|
|
76
|
-
y
|
|
77
|
-
]);
|
|
72
|
+
const safeLegend = legend || "groupType";
|
|
78
73
|
const safeZ = z;
|
|
79
74
|
const safeY = "groupValue";
|
|
80
75
|
const isCompare = timeRange?.compareStartTime !== "";
|
|
81
76
|
const chartConfig = config || {};
|
|
82
|
-
const { isDataTag =
|
|
77
|
+
const { isDataTag = true, isCombineDataTag = true, isLegend = true, isDescend = false, isHighlight = true } = chartConfig;
|
|
83
78
|
const [xyList, setXYList] = useState([]);
|
|
84
79
|
const [activeIds, setActiveIds] = useState([]);
|
|
85
80
|
const [legendItems, setLegendItems] = useState([]);
|
|
86
|
-
const transformedData = useMemo(()=>{
|
|
81
|
+
const { transformedData, leftData, rightData } = useMemo(()=>{
|
|
82
|
+
console.log("G2CombineChart left useMemo: legend:", legend, data, x, y, z, indicators);
|
|
87
83
|
if (!legend) {
|
|
88
84
|
let result = transformDataToGroupBarLineFormat(data, x, y, indicators);
|
|
89
85
|
data = result;
|
|
86
|
+
setIsOldData(true);
|
|
90
87
|
}
|
|
91
|
-
console.log("G2CombineChart transformedData2:", data);
|
|
92
|
-
const
|
|
88
|
+
console.log("G2CombineChart renderG2CombineChart transformedData2:", data);
|
|
89
|
+
const { transformedData, leftData, rightData } = DataAdapter.transform(data, "barLine", {
|
|
93
90
|
type: "barLine",
|
|
94
91
|
x,
|
|
95
92
|
y: safeY,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
x,
|
|
100
|
-
y: safeY,
|
|
101
|
-
z
|
|
93
|
+
z,
|
|
94
|
+
isDescend,
|
|
95
|
+
isGroup: isGroupRef.current
|
|
102
96
|
});
|
|
103
|
-
return
|
|
97
|
+
return {
|
|
98
|
+
transformedData: transformedData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap)),
|
|
99
|
+
leftData: leftData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap)),
|
|
100
|
+
rightData: rightData.map((item)=>dataTransform.processNodeInfo(item, contextConfig.nodeMap))
|
|
101
|
+
};
|
|
104
102
|
}, [
|
|
105
|
-
isGroup,
|
|
106
103
|
data,
|
|
107
104
|
x,
|
|
108
105
|
safeY,
|
|
109
106
|
z,
|
|
110
107
|
dataTransform,
|
|
111
|
-
contextConfig.nodeMap
|
|
108
|
+
contextConfig.nodeMap,
|
|
109
|
+
isDescend
|
|
112
110
|
]);
|
|
113
|
-
console.log("G2CombineChart transformedData:", transformedData);
|
|
111
|
+
console.log("G2CombineChart transformedData:", transformedData, leftData, rightData);
|
|
114
112
|
const { maxY } = useMemo(()=>{
|
|
115
|
-
const key =
|
|
113
|
+
const key = isGroupRef.current ? "total" : safeY;
|
|
116
114
|
const yValues = transformedData.filter((item)=>"-" !== item[key] && void 0 !== item[key] && null !== item[key]).map((item)=>Number(item[key]) || 0);
|
|
117
115
|
return {
|
|
118
116
|
maxY: yValues.length > 0 ? Math.max(...yValues) : 0
|
|
119
117
|
};
|
|
120
118
|
}, [
|
|
121
|
-
isGroup,
|
|
122
119
|
transformedData,
|
|
123
120
|
safeY
|
|
124
121
|
]);
|
|
125
|
-
const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap,
|
|
122
|
+
const formatAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, y), [
|
|
126
123
|
safeIndicatorMap,
|
|
127
|
-
|
|
124
|
+
y
|
|
128
125
|
]);
|
|
129
126
|
const formatLineAxis = useCallback((val)=>getAxisFormat(val, safeIndicatorMap, safeZ), [
|
|
130
127
|
safeIndicatorMap,
|
|
@@ -143,31 +140,53 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
143
140
|
const indicatorId = id.split("_")[0];
|
|
144
141
|
const isCombine = "true" === id.split("_")[1];
|
|
145
142
|
const lineGroupTypeIndex = lineGroupTypeArr.indexOf(id);
|
|
146
|
-
const color =
|
|
143
|
+
const color = isGroupRef.current ? isCombine ? lineColors[lineGroupTypeIndex] || lineColors[0] : themeColors[colorIndex] || themeColors[0] : 0 === colorIndex ? themeColors[colorIndex] : lineColors[colorIndex - 1];
|
|
147
144
|
return {
|
|
148
145
|
id,
|
|
149
|
-
label:
|
|
146
|
+
label: isGroupRef.current ? isCombine ? getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) : indicatorId : getIndicatorCompareName(safeIndicatorMap, String(indicatorId)) + (String(indicatorId).includes("_compare") ? `(对比时间:${timeRange?.compareStartTime}~${timeRange?.compareEndTime})` : ""),
|
|
150
147
|
color,
|
|
151
148
|
isCompare: String(indicatorId).includes("_compare"),
|
|
152
|
-
symbol:
|
|
149
|
+
symbol: isGroupRef.current ? isCombine ? "line" : "square" : 0 === colorIndex ? "square" : "line"
|
|
153
150
|
};
|
|
154
151
|
});
|
|
155
152
|
setLegendItems(items);
|
|
156
|
-
|
|
153
|
+
const newIds = items.map((i)=>i.id);
|
|
154
|
+
setActiveIds((prev)=>{
|
|
155
|
+
if (!prev.length) return newIds;
|
|
156
|
+
const newSet = new Set(newIds);
|
|
157
|
+
if (prev.length !== newIds.length || prev.some((id)=>!newSet.has(id))) return newIds;
|
|
158
|
+
return prev;
|
|
159
|
+
});
|
|
157
160
|
}, [
|
|
158
|
-
isGroup,
|
|
159
161
|
transformedData,
|
|
160
162
|
safeIndicatorMap,
|
|
161
|
-
themeColors
|
|
162
|
-
activeIds.length
|
|
163
|
+
themeColors
|
|
163
164
|
]);
|
|
164
|
-
const
|
|
165
|
-
if (!activeIds.length) return
|
|
166
|
-
|
|
165
|
+
const filterLeftData = useMemo(()=>{
|
|
166
|
+
if (!activeIds.length) return leftData;
|
|
167
|
+
const result = leftData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType.replace("_compare", "") + "_" + d.isCombine)) : true);
|
|
168
|
+
if (isGroupRef.current) result.forEach((item)=>{
|
|
169
|
+
item.total = result.filter((d)=>d.groupName === item.groupName).reduce((acc, d)=>acc + d.groupValue, 0);
|
|
170
|
+
});
|
|
171
|
+
return result;
|
|
167
172
|
}, [
|
|
168
|
-
|
|
173
|
+
leftData,
|
|
174
|
+
activeIds
|
|
175
|
+
]);
|
|
176
|
+
const filterRightData = useMemo(()=>{
|
|
177
|
+
if (!activeIds.length) return rightData;
|
|
178
|
+
return rightData.filter((d)=>d.groupType ? activeIds.includes(String(d.groupType.replace("_compare", "") + "_" + d.isCombine)) : true);
|
|
179
|
+
}, [
|
|
180
|
+
rightData,
|
|
169
181
|
activeIds
|
|
170
182
|
]);
|
|
183
|
+
const filteredData = useMemo(()=>[
|
|
184
|
+
...filterLeftData,
|
|
185
|
+
...filterRightData
|
|
186
|
+
], [
|
|
187
|
+
filterLeftData,
|
|
188
|
+
filterRightData
|
|
189
|
+
]);
|
|
171
190
|
const canvasMarginBottom = legendItems.length > 1 ? 2 === nodeSetting.showType ? 32 : 16 : 0;
|
|
172
191
|
const containerRef = useRef(null);
|
|
173
192
|
const chartRef = useRef(null);
|
|
@@ -192,12 +211,17 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
192
211
|
formatAxis,
|
|
193
212
|
formatLineAxis,
|
|
194
213
|
isDataTag,
|
|
214
|
+
isCombineDataTag,
|
|
195
215
|
isLegend: false,
|
|
196
216
|
isCompare,
|
|
217
|
+
isHighlight,
|
|
218
|
+
isClickable: !!onChartClick,
|
|
197
219
|
height: height - canvasMarginBottom,
|
|
198
|
-
formatLabel: isDataTag ? (d)=>{
|
|
220
|
+
formatLabel: (isDataTag || isCombineDataTag) && !isOldData ? (d)=>{
|
|
199
221
|
const indicatorId = d.groupType.split("_")[0];
|
|
200
|
-
|
|
222
|
+
const key = isGroupRef.current && !d.isCombine ? "total" : indicatorId;
|
|
223
|
+
if ("total" === key) return formatter.formatIndicator(d.total, safeIndicatorMap[y]);
|
|
224
|
+
return formatter.formatIndicator(d.groupValue, safeIndicatorMap[key]);
|
|
201
225
|
} : void 0,
|
|
202
226
|
indicators,
|
|
203
227
|
tooltipRender: (title, items)=>{
|
|
@@ -209,7 +233,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
209
233
|
}));
|
|
210
234
|
safeItems = safeItems.filter((i)=>i.indicatorId);
|
|
211
235
|
react_dom.render(/*#__PURE__*/ jsx(G2CompareTooltip, {
|
|
212
|
-
isGroupBar:
|
|
236
|
+
isGroupBar: isGroupRef.current,
|
|
213
237
|
title: title,
|
|
214
238
|
items: safeItems,
|
|
215
239
|
safeIndicatorMap: safeIndicatorMap,
|
|
@@ -221,6 +245,7 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
221
245
|
},
|
|
222
246
|
highlightDate: highlightDate ?? [],
|
|
223
247
|
timeRange,
|
|
248
|
+
auxiliaryLineData: auxiliaryLineData ?? [],
|
|
224
249
|
onNodeListChange: (nodes)=>{
|
|
225
250
|
setXYList(nodes);
|
|
226
251
|
},
|
|
@@ -232,14 +257,16 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
232
257
|
}
|
|
233
258
|
},
|
|
234
259
|
lineColors,
|
|
235
|
-
isGroup,
|
|
236
260
|
legendItems,
|
|
237
|
-
indicatorId: y
|
|
261
|
+
indicatorId: y,
|
|
262
|
+
isGroup: isGroupRef.current
|
|
238
263
|
});
|
|
239
264
|
chartRef.current = chart;
|
|
240
265
|
if (onChartClick) chart.on("element:click", (e)=>{
|
|
241
266
|
const datum = e.data?.data;
|
|
242
|
-
if (datum) onChartClick(
|
|
267
|
+
if (datum) onChartClick({
|
|
268
|
+
title: datum[x]
|
|
269
|
+
});
|
|
243
270
|
});
|
|
244
271
|
return ()=>{
|
|
245
272
|
if (chartRef.current) {
|
|
@@ -256,23 +283,22 @@ const G2CombineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorM
|
|
|
256
283
|
z,
|
|
257
284
|
maxY,
|
|
258
285
|
isDataTag,
|
|
259
|
-
|
|
286
|
+
isCombineDataTag,
|
|
287
|
+
isDescend,
|
|
260
288
|
themeColors,
|
|
261
289
|
safeIndicatorMap,
|
|
262
290
|
formatter,
|
|
263
291
|
formatAxis,
|
|
264
292
|
onChartClick,
|
|
265
|
-
|
|
266
|
-
|
|
293
|
+
isLegend,
|
|
294
|
+
isHighlight,
|
|
295
|
+
legendItems,
|
|
296
|
+
auxiliaryLineData,
|
|
297
|
+
leftData,
|
|
298
|
+
rightData,
|
|
299
|
+
isOldData
|
|
267
300
|
]);
|
|
268
|
-
|
|
269
|
-
style: {
|
|
270
|
-
width: "100%",
|
|
271
|
-
color: "#86909c",
|
|
272
|
-
padding: 16
|
|
273
|
-
},
|
|
274
|
-
children: "请传入 z 作为折线指标字段,以展示柱状+折线组合图。"
|
|
275
|
-
});
|
|
301
|
+
console.log("G2BarLegend items: combie", legendItems, activeIds);
|
|
276
302
|
return /*#__PURE__*/ jsxs("div", {
|
|
277
303
|
style: {
|
|
278
304
|
width: "100%",
|
|
@@ -12,11 +12,11 @@ import useG2TooltipContainer from "../shared/useG2TooltipContainer.js";
|
|
|
12
12
|
import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
|
|
13
13
|
import { G2BarLegend } from "./G2BarLegend.js";
|
|
14
14
|
import { renderG2LineChart } from "./g2line.js";
|
|
15
|
-
const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick
|
|
15
|
+
const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap, onChartClick, timeRange, legend = "", config, nodeSetting = {
|
|
16
16
|
showType: 0,
|
|
17
17
|
type: []
|
|
18
18
|
}, auxiliaryLineData, highlightDate, indicators = [] })=>{
|
|
19
|
-
console.log("props data: G2LineChart", data, nodeSetting, config, "x, y, z", x, y, z, "highlightDate:", highlightDate);
|
|
19
|
+
console.log("props data: G2LineChart", data, nodeSetting, config, "x, y, z", x, y, z, "highlightDate:", highlightDate, "indicators:", indicators);
|
|
20
20
|
const { formatter, dataTransform, config: contextConfig } = useChartContext();
|
|
21
21
|
const tooltipContainerRef = useG2TooltipContainer();
|
|
22
22
|
const themeColors = contextConfig?.theme?.colors || [];
|
|
@@ -94,12 +94,17 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
|
|
|
94
94
|
};
|
|
95
95
|
});
|
|
96
96
|
setLegendItems(items);
|
|
97
|
-
|
|
97
|
+
const newIds = items.map((i)=>i.id);
|
|
98
|
+
setActiveIds((prev)=>{
|
|
99
|
+
if (!prev.length) return newIds;
|
|
100
|
+
const newSet = new Set(newIds);
|
|
101
|
+
if (prev.length !== newIds.length || prev.some((id)=>!newSet.has(id))) return newIds;
|
|
102
|
+
return prev;
|
|
103
|
+
});
|
|
98
104
|
}, [
|
|
99
105
|
transformedData,
|
|
100
106
|
safeIndicatorMap,
|
|
101
|
-
themeColors
|
|
102
|
-
activeIds.length
|
|
107
|
+
themeColors
|
|
103
108
|
]);
|
|
104
109
|
const filteredData = useMemo(()=>{
|
|
105
110
|
if (!activeIds.length) return transformedData;
|
|
@@ -123,7 +128,7 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
|
|
|
123
128
|
minY,
|
|
124
129
|
maxY,
|
|
125
130
|
themeColors,
|
|
126
|
-
indicators,
|
|
131
|
+
indicators: indicators || activeIds,
|
|
127
132
|
indicatorMap: safeIndicatorMap,
|
|
128
133
|
formatAxis,
|
|
129
134
|
highlightDate: highlightDate ?? [],
|
|
@@ -169,6 +174,12 @@ const G2LineChart = ({ height = 300, data, x = "", y = "", z = "", indicatorMap,
|
|
|
169
174
|
}
|
|
170
175
|
});
|
|
171
176
|
chartRef.current = chart;
|
|
177
|
+
if (onChartClick) chart.on("element:click", (e)=>{
|
|
178
|
+
const datum = e.data?.data;
|
|
179
|
+
if (datum) onChartClick({
|
|
180
|
+
title: datum[x]
|
|
181
|
+
});
|
|
182
|
+
});
|
|
172
183
|
return ()=>{
|
|
173
184
|
if (chartRef.current) {
|
|
174
185
|
chartRef.current.off("element:click");
|
|
@@ -216,6 +216,7 @@ export interface ScaleYLinearOptions {
|
|
|
216
216
|
export declare function applyScaleYLinear(view: any, options?: ScaleYLinearOptions): void;
|
|
217
217
|
export interface ApplyAxisXOptions {
|
|
218
218
|
title?: boolean;
|
|
219
|
+
isHorizontal?: boolean;
|
|
219
220
|
labelAutoHide?: 'greedy' | 'equidistant' | boolean;
|
|
220
221
|
/** 为 true 时刻度过多会自动旋转为垂直;为 false 时保持水平,依赖 labelAutoHide 避免重叠。默认 false */
|
|
221
222
|
labelAutoRotate?: boolean;
|
|
@@ -271,6 +272,7 @@ export declare function applyLegendColor(view: any, options?: ApplyLegendColorOp
|
|
|
271
272
|
export interface AuxiliaryLineItem {
|
|
272
273
|
name: string;
|
|
273
274
|
value: number;
|
|
275
|
+
axis?: 'left' | 'right';
|
|
274
276
|
}
|
|
275
277
|
export interface ApplyAuxiliaryLineYOptions {
|
|
276
278
|
stroke?: string;
|
|
@@ -291,3 +293,4 @@ export interface GetColorByGroupTypeOptions {
|
|
|
291
293
|
*/
|
|
292
294
|
export declare function getColorByGroupType(groupType: string, options: GetColorByGroupTypeOptions): string;
|
|
293
295
|
export declare function applyHighlightDate(view: any, x: string, data: any, highlightDate: string[], isHighlight: boolean): void;
|
|
296
|
+
export declare function adjustDomainMax(domainMin: number, domainMax: number): number;
|
|
@@ -19,7 +19,7 @@ function applyScaleYLinear(view, options = {}) {
|
|
|
19
19
|
[field]: {
|
|
20
20
|
type: 'linear',
|
|
21
21
|
...null != domainMax && {
|
|
22
|
-
domainMax
|
|
22
|
+
domainMax: adjustDomainMax(domainMin, domainMax)
|
|
23
23
|
},
|
|
24
24
|
domainMin,
|
|
25
25
|
clamp,
|
|
@@ -38,7 +38,7 @@ function applyScaleYLinear(view, options = {}) {
|
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
function applyAxisX(mark, options = {}) {
|
|
41
|
-
const { title = false,
|
|
41
|
+
const { title = false, grid = true, gridStroke = '#333', gridLineWidth = 50, gridLineDash = [
|
|
42
42
|
1000
|
|
43
43
|
], gridFilter } = options;
|
|
44
44
|
mark.axis('x', {
|
|
@@ -50,16 +50,19 @@ function applyAxisX(mark, options = {}) {
|
|
|
50
50
|
...gridFilter && {
|
|
51
51
|
gridFilter
|
|
52
52
|
},
|
|
53
|
+
labelAutoRotate: false,
|
|
54
|
+
labelFontSize: 12,
|
|
55
|
+
labelFontColor: '#000',
|
|
56
|
+
labelAutoEllipsis: {
|
|
57
|
+
type: 'ellipsis',
|
|
58
|
+
maxLength: 50
|
|
59
|
+
},
|
|
60
|
+
labelAlign: 'horizontal',
|
|
53
61
|
labelAutoHide: {
|
|
54
62
|
type: 'hide',
|
|
55
63
|
keepHeader: true,
|
|
56
64
|
keepTail: true
|
|
57
|
-
}
|
|
58
|
-
labelAutoRotate,
|
|
59
|
-
labelFontSize: 12,
|
|
60
|
-
labelFontColor: '#000',
|
|
61
|
-
labelAutoEllipsis: true,
|
|
62
|
-
labelFontOpacity: 1
|
|
65
|
+
}
|
|
63
66
|
});
|
|
64
67
|
}
|
|
65
68
|
function applyAxisY(mark, options = {}) {
|
|
@@ -123,11 +126,16 @@ function applyAuxiliaryLineY(view, lines, options = {}) {
|
|
|
123
126
|
console.log('applyAuxiliaryLineY:', lines);
|
|
124
127
|
const { stroke = '#F4664A', strokeOpacity = 1, labelMaxLength = 5 } = options;
|
|
125
128
|
lines.forEach((auxLine)=>{
|
|
126
|
-
view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').
|
|
129
|
+
view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').axis('y', {
|
|
130
|
+
title: false,
|
|
131
|
+
grid: false,
|
|
132
|
+
label: false,
|
|
133
|
+
tick: false
|
|
134
|
+
}).label({
|
|
127
135
|
dx: 0,
|
|
128
136
|
dy: -5,
|
|
129
137
|
text: splitTextToMultiline(auxLine.name, labelMaxLength, '<br />'),
|
|
130
|
-
position: 'bottom-left',
|
|
138
|
+
position: auxLine?.axis === 'right' ? 'bottom-right' : 'bottom-left',
|
|
131
139
|
style: {},
|
|
132
140
|
render: (text)=>`<div style="background-color: transparent; padding: 5px; border-radius: 5px;font-size: 12px;position: absolute;left: -4px; top: -24px; width: 100px;color: ${stroke}; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;">${text}</div>`
|
|
133
141
|
});
|
|
@@ -179,4 +187,7 @@ function applyHighlightDate(view, x, data, highlightDate, isHighlight) {
|
|
|
179
187
|
strokeOpacity: 0
|
|
180
188
|
});
|
|
181
189
|
}
|
|
182
|
-
|
|
190
|
+
function adjustDomainMax(domainMin, domainMax) {
|
|
191
|
+
return domainMax === domainMin ? domainMin > 0 ? 1.1 * domainMax : domainMax + 1 : domainMax;
|
|
192
|
+
}
|
|
193
|
+
export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyScaleYLinear, createChart, getColorByGroupType, getMainView };
|
|
@@ -33,6 +33,8 @@ export interface RenderG2BarChartOptions {
|
|
|
33
33
|
isHighlight?: boolean;
|
|
34
34
|
/** 图例字段名(与 y 不同时表示分组柱),通常为 groupType */
|
|
35
35
|
isCompare?: boolean;
|
|
36
|
+
/** 是否启用点击事件 */
|
|
37
|
+
isClickable?: boolean;
|
|
36
38
|
legend?: string;
|
|
37
39
|
/** 数据标签格式化:formatLabel(datum) */
|
|
38
40
|
formatLabel?: (datum: any) => string;
|
|
@@ -2,7 +2,7 @@ import { lines } from "@antv/g-pattern";
|
|
|
2
2
|
import { applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyScaleYLinear, createChart, getColorByGroupType, getMainView } from "./g2Helpers.js";
|
|
3
3
|
const Y_AXIS_FIELD = 'groupValue';
|
|
4
4
|
function renderG2BarChart(container, options) {
|
|
5
|
-
const { data, x, y, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], isDataTag = false, isLegend = true, isHorizontal = false, isHighlight = true, isCompare = false, legend, formatLabel, height = 300, tooltipRender, auxiliaryLineData = [], onNodeListChange, onChartRender } = options;
|
|
5
|
+
const { data, x, y, maxY, timeRange: _timeRange, themeColors, indicators = [], indicatorMap: _indicatorMap = {}, formatAxis, highlightDate = [], isDataTag = false, isLegend = true, isHorizontal = false, isHighlight = true, isCompare = false, isClickable = false, legend, formatLabel, height = 300, tooltipRender, auxiliaryLineData = [], onNodeListChange, onChartRender } = options;
|
|
6
6
|
const colorOpts = {
|
|
7
7
|
themeColors,
|
|
8
8
|
primaryKey: y,
|
|
@@ -20,7 +20,7 @@ function renderG2BarChart(container, options) {
|
|
|
20
20
|
});
|
|
21
21
|
console.log('isLegend:', legend, isLegend);
|
|
22
22
|
const view = getMainView(chart);
|
|
23
|
-
view.attr('marginBottom', isLegend ? 0 : 16);
|
|
23
|
+
view.attr('marginLeft', 0).attr('marginBottom', isLegend ? 0 : 16);
|
|
24
24
|
if (isHorizontal) view.coordinate({
|
|
25
25
|
transform: [
|
|
26
26
|
{
|
|
@@ -46,13 +46,13 @@ function renderG2BarChart(container, options) {
|
|
|
46
46
|
columnWidthRatio: 0.6,
|
|
47
47
|
insetLeft: (_d, index, _data, _column)=>{
|
|
48
48
|
if (isHorizontal) return 0;
|
|
49
|
-
if (isCompare) return index % 2 === 0 ?
|
|
50
|
-
return
|
|
49
|
+
if (isCompare) return index % 2 === 0 ? 0 : 0;
|
|
50
|
+
return 0;
|
|
51
51
|
},
|
|
52
52
|
insetRight: (_d, index, _data, _column)=>{
|
|
53
53
|
if (isHorizontal) return 0;
|
|
54
|
-
if (isCompare) return index % 2 === 1 ?
|
|
55
|
-
return
|
|
54
|
+
if (isCompare) return index % 2 === 1 ? 0 : 0;
|
|
55
|
+
return 0;
|
|
56
56
|
},
|
|
57
57
|
fill: (datum)=>{
|
|
58
58
|
const groupType = String(datum.groupType ?? '');
|
|
@@ -68,10 +68,12 @@ function renderG2BarChart(container, options) {
|
|
|
68
68
|
transform: 'rotate(-30deg)'
|
|
69
69
|
};
|
|
70
70
|
return getColorByGroupType(groupType, colorOpts);
|
|
71
|
-
}
|
|
71
|
+
},
|
|
72
|
+
cursor: isClickable ? 'pointer' : 'default'
|
|
72
73
|
});
|
|
73
74
|
applyAxisX(view, {
|
|
74
|
-
grid: false
|
|
75
|
+
grid: false,
|
|
76
|
+
isHorizontal
|
|
75
77
|
});
|
|
76
78
|
applyAxisY(view, {
|
|
77
79
|
labelFormatter: formatAxis
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Chart } from "@antv/g2";
|
|
6
6
|
import type { ChartTimeRange, IndicatorInfo } from "../../../core/ChartTypes";
|
|
7
|
+
import { type AuxiliaryLineItem } from "./g2Helpers";
|
|
7
8
|
export interface RenderG2CombineChartOptions {
|
|
8
9
|
/** 已转换后的数据:约定包含 groupName、groupType、groupValue 等字段 */
|
|
9
10
|
data: any[];
|
|
@@ -27,12 +28,16 @@ export interface RenderG2CombineChartOptions {
|
|
|
27
28
|
formatLineAxis: (val: any) => string;
|
|
28
29
|
/** 是否显示数据标签 */
|
|
29
30
|
isDataTag?: boolean;
|
|
31
|
+
/** 是否显示副轴数据标签 */
|
|
32
|
+
isCombineDataTag?: boolean;
|
|
30
33
|
/** 是否显示自定义 Legend(仅影响 React 层,G2 内部不画 legend) */
|
|
31
34
|
isLegend?: boolean;
|
|
32
35
|
/** 是否启用图例高亮 */
|
|
33
36
|
isHighlight?: boolean;
|
|
34
37
|
/** 是否启用对比期 */
|
|
35
38
|
isCompare?: boolean;
|
|
39
|
+
/** 是否启用点击事件 */
|
|
40
|
+
isClickable?: boolean;
|
|
36
41
|
/** 数据标签格式化:formatLabel(datum) */
|
|
37
42
|
formatLabel?: (datum: any) => string;
|
|
38
43
|
/** 图表高度 */
|
|
@@ -49,6 +54,8 @@ export interface RenderG2CombineChartOptions {
|
|
|
49
54
|
isChange?: boolean;
|
|
50
55
|
compareTime?: string;
|
|
51
56
|
}>) => HTMLElement | null;
|
|
57
|
+
/** 辅助线 */
|
|
58
|
+
auxiliaryLineData?: AuxiliaryLineItem[];
|
|
52
59
|
/** 将计算出的节点信息传递给外层(用于渲染 NodePopover 等) */
|
|
53
60
|
onNodeListChange?: (nodes: Array<{
|
|
54
61
|
pointP: {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { lines } from "@antv/g-pattern";
|
|
2
|
-
import { applyAxisX, applyHighlightDate, createChart, getMainView } from "./g2Helpers.js";
|
|
2
|
+
import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, createChart, getMainView } from "./g2Helpers.js";
|
|
3
3
|
import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
|
|
4
4
|
const Y_AXIS_FIELD = 'groupValue';
|
|
5
5
|
const BAR_Y_FIELD = 'barValue';
|
|
6
6
|
const LINE_Y_FIELD = 'lineValue';
|
|
7
7
|
function renderG2CombineChart(container, options) {
|
|
8
|
-
const { data, x, y, z: _z, maxY, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag =
|
|
8
|
+
const { data, x, y, z: _z, maxY, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag = true, isCombineDataTag = true, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, isClickable = false, indicators = [], tooltipRender, auxiliaryLineData = [], onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId } = options;
|
|
9
9
|
const chart = createChart({
|
|
10
10
|
container,
|
|
11
11
|
height,
|
|
@@ -17,7 +17,7 @@ function renderG2CombineChart(container, options) {
|
|
|
17
17
|
insetBottom: 0
|
|
18
18
|
});
|
|
19
19
|
const view = getMainView(chart);
|
|
20
|
-
view.attr('marginBottom', 0);
|
|
20
|
+
view.attr('insetLeft', 0).attr('insetRight', 0).attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', 0);
|
|
21
21
|
console.log('renderG2CombineChart data:', data, 'maxY:', maxY, x, y, 'indicators:', indicators);
|
|
22
22
|
view.data(data);
|
|
23
23
|
applyAxisX(view, {
|
|
@@ -26,16 +26,20 @@ function renderG2CombineChart(container, options) {
|
|
|
26
26
|
});
|
|
27
27
|
const barColor = themeColors[0] ?? "#5B8FF9";
|
|
28
28
|
console.log('tooltip: themeColors:', themeColors[0], barColor, isGroup);
|
|
29
|
-
console.log('renderG2CombineChart
|
|
29
|
+
console.log('renderG2CombineChart highlightDate:', highlightDate, isHighlight);
|
|
30
30
|
applyHighlightDate(view, x, data, highlightDate, isHighlight);
|
|
31
31
|
const intervalData = data.filter((item)=>!item.isCombine).map((item)=>({
|
|
32
32
|
...item,
|
|
33
33
|
[BAR_Y_FIELD]: item[Y_AXIS_FIELD]
|
|
34
34
|
}));
|
|
35
|
+
console.log('renderG2CombineChart interval data:', intervalData);
|
|
35
36
|
const intervalMaxY = intervalData.reduce((max, item)=>{
|
|
36
37
|
const key = isGroup ? "total" : BAR_Y_FIELD;
|
|
37
38
|
return Math.max(max, item[key]);
|
|
38
39
|
}, 0);
|
|
40
|
+
const auxValues = auxiliaryLineData?.length ? auxiliaryLineData.map((item)=>item.value) : [];
|
|
41
|
+
const maxAux = auxValues.length ? Math.max(...auxValues) : 0;
|
|
42
|
+
const finalIntervalMax = Math.max(intervalMaxY, maxAux);
|
|
39
43
|
const interval = view.interval().data(intervalData).encode("x", x).encode("y", BAR_Y_FIELD).encode("color", "groupType").transform(isGroup ? {
|
|
40
44
|
type: 'stackY',
|
|
41
45
|
reverse: true
|
|
@@ -71,12 +75,13 @@ function renderG2CombineChart(container, options) {
|
|
|
71
75
|
};
|
|
72
76
|
return barColor;
|
|
73
77
|
},
|
|
78
|
+
cursor: isClickable ? 'pointer' : 'default',
|
|
74
79
|
stroke: 'transparent'
|
|
75
80
|
});
|
|
76
81
|
interval.scale('y', {
|
|
77
82
|
type: 'linear',
|
|
78
83
|
domainMin: 0,
|
|
79
|
-
domainMax:
|
|
84
|
+
domainMax: finalIntervalMax,
|
|
80
85
|
nice: true,
|
|
81
86
|
clamp: true,
|
|
82
87
|
key: 'bar',
|
|
@@ -103,6 +108,7 @@ function renderG2CombineChart(container, options) {
|
|
|
103
108
|
(datum)=>{
|
|
104
109
|
const groupType = String(datum.groupType ?? '');
|
|
105
110
|
const index = legendItems.findIndex((item)=>item.id === `${groupType}_${datum.isCombine}`);
|
|
111
|
+
console.log(datum);
|
|
106
112
|
return {
|
|
107
113
|
value: datum[Y_AXIS_FIELD],
|
|
108
114
|
name: datum['groupType'],
|
|
@@ -141,11 +147,11 @@ function renderG2CombineChart(container, options) {
|
|
|
141
147
|
} : false : false
|
|
142
148
|
].filter(Boolean)
|
|
143
149
|
});
|
|
144
|
-
console.log('renderG2CombineChart: line data:', data.filter((item)=>item.isCombine));
|
|
145
150
|
const lineData = data.filter((item)=>item.isCombine && !item.groupType.includes('_compare')).map((item)=>({
|
|
146
151
|
...item,
|
|
147
152
|
[LINE_Y_FIELD]: item[Y_AXIS_FIELD]
|
|
148
153
|
}));
|
|
154
|
+
console.log('renderG2CombineChart: line data:', lineData);
|
|
149
155
|
const compareLineData = data.filter((item)=>item.isCombine && item.groupType.includes('_compare')).map((item)=>({
|
|
150
156
|
...item,
|
|
151
157
|
[LINE_Y_FIELD]: item[Y_AXIS_FIELD]
|
|
@@ -153,8 +159,8 @@ function renderG2CombineChart(container, options) {
|
|
|
153
159
|
console.log('compareLineData:', compareLineData);
|
|
154
160
|
const lineMaxY = lineData.reduce((max, item)=>Math.max(max, item[LINE_Y_FIELD]), 0);
|
|
155
161
|
const compareLineMaxY = compareLineData.reduce((max, item)=>Math.max(max, item[LINE_Y_FIELD]), 0);
|
|
156
|
-
const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY);
|
|
157
|
-
|
|
162
|
+
const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY) || 1;
|
|
163
|
+
const finalLineMax = Math.max(lineFinalMaxY, maxAux);
|
|
158
164
|
const line = view.line().data(lineData).encode("x", x).encode("y", LINE_Y_FIELD).encode('color', 'groupType').style({
|
|
159
165
|
lineWidth: 2,
|
|
160
166
|
stroke: (datum)=>{
|
|
@@ -164,7 +170,7 @@ function renderG2CombineChart(container, options) {
|
|
|
164
170
|
];
|
|
165
171
|
const groupType = String(datum[0]?.groupType ?? '');
|
|
166
172
|
const index = groupTypeArr.findIndex((item)=>item === groupType);
|
|
167
|
-
const color =
|
|
173
|
+
const color = lineColors[index] || lineColors[0];
|
|
168
174
|
return color;
|
|
169
175
|
}
|
|
170
176
|
});
|
|
@@ -175,14 +181,14 @@ function renderG2CombineChart(container, options) {
|
|
|
175
181
|
const groupTypeArr = [
|
|
176
182
|
...groupTypeSet
|
|
177
183
|
];
|
|
178
|
-
const groupType = String(datum
|
|
184
|
+
const groupType = String(datum?.groupType ?? '');
|
|
179
185
|
const index = groupTypeArr.findIndex((item)=>item === groupType);
|
|
180
186
|
return {
|
|
181
187
|
value: datum[LINE_Y_FIELD],
|
|
182
|
-
name:
|
|
188
|
+
name: getIndicatorCompareName(_indicatorMap, datum['groupType']),
|
|
183
189
|
indicatorId: datum['groupType'],
|
|
184
190
|
channel: Y_AXIS_FIELD,
|
|
185
|
-
color:
|
|
191
|
+
color: lineColors[index] || lineColors[0],
|
|
186
192
|
isCombine: true,
|
|
187
193
|
tipType: 'line'
|
|
188
194
|
};
|
|
@@ -192,10 +198,10 @@ function renderG2CombineChart(container, options) {
|
|
|
192
198
|
line.scale('y', {
|
|
193
199
|
type: 'linear',
|
|
194
200
|
domainMin: 0,
|
|
195
|
-
domainMax:
|
|
201
|
+
domainMax: finalLineMax,
|
|
196
202
|
nice: true,
|
|
197
203
|
clamp: true,
|
|
198
|
-
key: '
|
|
204
|
+
key: 'line',
|
|
199
205
|
independent: true,
|
|
200
206
|
tickMethod: (min, max)=>Array.from({
|
|
201
207
|
length: 6
|
|
@@ -221,15 +227,23 @@ function renderG2CombineChart(container, options) {
|
|
|
221
227
|
4
|
|
222
228
|
],
|
|
223
229
|
lineWidth: 2,
|
|
224
|
-
stroke: (datum
|
|
230
|
+
stroke: (datum)=>{
|
|
225
231
|
const groupType = String(datum[0]?.groupType ?? '');
|
|
226
232
|
const color = lineColors[indicators.slice(1).indexOf(String(groupType.replace('_compare', ''))) ?? 0];
|
|
227
|
-
console.log('compareLine: 222', 'index:', index, 'indicators:', indicators, 'datum:', datum, 'groupType:', groupType, 'color:', color);
|
|
228
233
|
return color ?? 'transparent';
|
|
229
234
|
}
|
|
230
235
|
});
|
|
231
236
|
compareLine.scale('y', {
|
|
232
|
-
|
|
237
|
+
type: 'linear',
|
|
238
|
+
domainMin: 0,
|
|
239
|
+
domainMax: finalLineMax,
|
|
240
|
+
nice: true,
|
|
241
|
+
clamp: true,
|
|
242
|
+
key: 'line',
|
|
243
|
+
independent: true,
|
|
244
|
+
tickMethod: (min, max)=>Array.from({
|
|
245
|
+
length: 6
|
|
246
|
+
}, (_, i)=>min + (max - min) * i / 5)
|
|
233
247
|
});
|
|
234
248
|
compareLine.axis('y', false);
|
|
235
249
|
const hasCompareData = data.some((item)=>item.groupType.includes('_compare'));
|
|
@@ -265,33 +279,31 @@ function renderG2CombineChart(container, options) {
|
|
|
265
279
|
const { title, items } = payload;
|
|
266
280
|
const baseItems = items.filter((item)=>!item.isCombine);
|
|
267
281
|
const combineItems = items.filter((item)=>item.isCombine);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
282
|
+
const indicatorOrder = new Map(indicators.map((id, i)=>[
|
|
283
|
+
id,
|
|
284
|
+
i
|
|
285
|
+
]));
|
|
286
|
+
const sortedCombineItems = [
|
|
271
287
|
...combineItems
|
|
288
|
+
].sort((a, b)=>{
|
|
289
|
+
const orderA = indicatorOrder.get(a.indicatorId) ?? 1 / 0;
|
|
290
|
+
const orderB = indicatorOrder.get(b.indicatorId) ?? 1 / 0;
|
|
291
|
+
if (orderA !== orderB) return orderA - orderB;
|
|
292
|
+
const typeRank = (item)=>{
|
|
293
|
+
if (item.isChange) return 2;
|
|
294
|
+
if ('compareline' === item.tipType) return 1;
|
|
295
|
+
return 0;
|
|
296
|
+
};
|
|
297
|
+
return typeRank(a) - typeRank(b);
|
|
298
|
+
});
|
|
299
|
+
return tooltipRender(title, [
|
|
300
|
+
...baseItems,
|
|
301
|
+
...sortedCombineItems
|
|
272
302
|
]) ?? null;
|
|
273
|
-
if (indicators.length) {
|
|
274
|
-
const groupedItems = indicators.map((indicator, index)=>{
|
|
275
|
-
if (0 === index) return items.filter((i)=>!i.isCombine).filter((i)=>i.indicatorId === String(indicator));
|
|
276
|
-
return items.filter((i)=>i.isCombine).filter((i)=>i.indicatorId === String(indicator));
|
|
277
|
-
});
|
|
278
|
-
console.log(groupedItems.flat(), 'tooltip groupedItems');
|
|
279
|
-
const sortedItems = groupedItems.map((group)=>[
|
|
280
|
-
group.filter((i)=>i.name === i.indicatorId),
|
|
281
|
-
group.filter((i)=>i.compareTime),
|
|
282
|
-
group.filter((i)=>i.name.includes('_change'))
|
|
283
|
-
].filter(Boolean).flat()).flat();
|
|
284
|
-
console.log(sortedItems, 'tooltip sortedItems');
|
|
285
|
-
const formatItems = sortedItems.map((item)=>({
|
|
286
|
-
...item,
|
|
287
|
-
color: item.isCombine ? lineColors[indicators.slice(1).indexOf(String(item?.indicatorId)) ?? 0] || barColor || 'transparent' : barColor || 'transparent'
|
|
288
|
-
}));
|
|
289
|
-
console.log(formatItems, 'tooltip formatItems');
|
|
290
|
-
return tooltipRender(title, formatItems ?? []) ?? null;
|
|
291
|
-
}
|
|
292
303
|
}
|
|
293
304
|
});
|
|
294
305
|
view.legend(false);
|
|
306
|
+
applyAuxiliaryLineY(view, auxiliaryLineData);
|
|
295
307
|
const nodeList = [];
|
|
296
308
|
console.log('nodeList data:', data);
|
|
297
309
|
data.forEach((item)=>{
|
|
@@ -354,35 +366,45 @@ function renderG2CombineChart(container, options) {
|
|
|
354
366
|
}
|
|
355
367
|
});
|
|
356
368
|
});
|
|
357
|
-
if (
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
369
|
+
if (formatLabel) {
|
|
370
|
+
if (isDataTag) {
|
|
371
|
+
const groupedByX = intervalData.reduce((acc, item)=>{
|
|
372
|
+
const key = item[x];
|
|
373
|
+
if (!acc[key]) acc[key] = [];
|
|
374
|
+
acc[key].push(item);
|
|
375
|
+
return acc;
|
|
376
|
+
}, {});
|
|
377
|
+
const lastItemsInEachStack = new Set();
|
|
378
|
+
Object.values(groupedByX).forEach((group)=>{
|
|
379
|
+
const lastItem = group[0];
|
|
380
|
+
lastItemsInEachStack.add(lastItem);
|
|
381
|
+
});
|
|
382
|
+
interval.label({
|
|
383
|
+
dy: -16,
|
|
384
|
+
dx: -10,
|
|
385
|
+
offset: 0,
|
|
386
|
+
text: (d)=>{
|
|
387
|
+
if (!isGroup) return formatLabel(d);
|
|
388
|
+
if (lastItemsInEachStack.has(d)) return formatLabel(d);
|
|
389
|
+
return '';
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (isCombineDataTag) line.label({
|
|
381
394
|
dy: -10,
|
|
382
|
-
dx:
|
|
395
|
+
dx: 10,
|
|
383
396
|
offset: 0,
|
|
384
397
|
text: (d)=>formatLabel(d)
|
|
385
398
|
});
|
|
399
|
+
view.labelTransform([
|
|
400
|
+
{
|
|
401
|
+
type: 'exceedAdjust',
|
|
402
|
+
bounds: 'main'
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
type: 'overlapHide'
|
|
406
|
+
}
|
|
407
|
+
]);
|
|
386
408
|
}
|
|
387
409
|
chart.render();
|
|
388
410
|
let hasEmittedNodeList = false;
|
|
@@ -19,7 +19,7 @@ function renderG2LineChart(container, options) {
|
|
|
19
19
|
insetBottom: 0
|
|
20
20
|
});
|
|
21
21
|
const view = getMainView(chart);
|
|
22
|
-
view.attr('marginBottom', isLegend ? 0 : 16);
|
|
22
|
+
view.attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', isLegend ? 0 : 16);
|
|
23
23
|
view.data(data);
|
|
24
24
|
const domainMin = minY ?? 0;
|
|
25
25
|
applyScaleYLinear(view, {
|
|
@@ -174,7 +174,11 @@ function renderG2LineChart(container, options) {
|
|
|
174
174
|
});
|
|
175
175
|
view.labelTransform([
|
|
176
176
|
{
|
|
177
|
-
type: '
|
|
177
|
+
type: 'exceedAdjust',
|
|
178
|
+
bounds: 'main'
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'overlapHide'
|
|
178
182
|
}
|
|
179
183
|
]);
|
|
180
184
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@publishfx/publish-chart",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "A React chart component library for the Publish platform, including BarChart, LineChart, BarLineChart and other visualization components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -24,20 +24,10 @@
|
|
|
24
24
|
"CHANGELOG.md",
|
|
25
25
|
"README.md"
|
|
26
26
|
],
|
|
27
|
-
"scripts": {
|
|
28
|
-
"build": "rslib build",
|
|
29
|
-
"dev": "rslib build --watch",
|
|
30
|
-
"lint": "eslint src --ext .ts,.tsx",
|
|
31
|
-
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
32
|
-
"test": "jest",
|
|
33
|
-
"test:watch": "jest --watch",
|
|
34
|
-
"test:coverage": "jest --coverage"
|
|
35
|
-
},
|
|
36
27
|
"devDependencies": {
|
|
37
28
|
"@antv/data-set": "^0.11.8",
|
|
38
29
|
"@antv/g-pattern": "^2.0.42",
|
|
39
30
|
"@antv/g2": "^5.3.0",
|
|
40
|
-
"@publishfx/publish-components": "workspace:^",
|
|
41
31
|
"@types/jest": "^29.5.12",
|
|
42
32
|
"@types/lodash": "^4.17.20",
|
|
43
33
|
"@types/react": "^18.3.18",
|
|
@@ -55,7 +45,8 @@
|
|
|
55
45
|
"react-dom": "^18.3.1",
|
|
56
46
|
"styled-components": "^5.3.11",
|
|
57
47
|
"ts-jest": "^29.1.2",
|
|
58
|
-
"typescript": "^5.9.3"
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"@publishfx/publish-components": "^2.1.0"
|
|
59
50
|
},
|
|
60
51
|
"peerDependencies": {
|
|
61
52
|
"@antv/data-set": "^0.11.8",
|
|
@@ -71,5 +62,14 @@
|
|
|
71
62
|
"publishConfig": {
|
|
72
63
|
"access": "public",
|
|
73
64
|
"registry": "https://registry.npmjs.org/"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "rslib build",
|
|
68
|
+
"dev": "rslib build --watch",
|
|
69
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
70
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
71
|
+
"test": "jest",
|
|
72
|
+
"test:watch": "jest --watch",
|
|
73
|
+
"test:coverage": "jest --coverage"
|
|
74
74
|
}
|
|
75
|
-
}
|
|
75
|
+
}
|