Skip to content

Commit ef6c0bf

Browse files
committed
feat(interaction): 透视表支持隐藏列头
1 parent 29b8617 commit ef6c0bf

File tree

12 files changed

+326
-203
lines changed

12 files changed

+326
-203
lines changed

packages/s2-core/__tests__/unit/utils/hide-columns.spec.ts renamed to packages/s2-core/__tests__/unit/utils/hide-columns-spec.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import {
77
isLastColumnAfterHidden,
88
hideColumns,
99
hideColumnsByThunkGroup,
10+
getValidDisplaySiblingNode,
11+
getValidDisplaySiblingNodeId,
12+
isEqualDisplaySiblingNodeId,
1013
} from '@/utils/hide-columns';
1114
import { PivotSheet, SpreadSheet } from '@/sheet-type';
1215
import { S2Event } from '@/common/constant';
@@ -262,4 +265,68 @@ describe('hide-columns test', () => {
262265

263266
expect(mockSpreadSheetInstance.render).not.toHaveBeenCalled();
264267
});
268+
269+
describe('Valid Display Sibling Node Tests', () => {
270+
const nextNode = {
271+
id: 'next',
272+
} as Node;
273+
const prevNode = {
274+
id: 'prev',
275+
} as Node;
276+
277+
test('should get display sibling node', () => {
278+
expect(
279+
getValidDisplaySiblingNode({ next: nextNode, prev: prevNode }),
280+
).toEqual(nextNode);
281+
282+
expect(
283+
getValidDisplaySiblingNode({ next: nextNode, prev: null }),
284+
).toEqual(nextNode);
285+
expect(
286+
getValidDisplaySiblingNode({ next: null, prev: prevNode }),
287+
).toEqual(prevNode);
288+
expect(getValidDisplaySiblingNode({ next: null, prev: null })).toEqual(
289+
null,
290+
);
291+
});
292+
293+
test('should get display sibling node id', () => {
294+
expect(
295+
getValidDisplaySiblingNodeId({ next: nextNode, prev: prevNode }),
296+
).toEqual(nextNode.id);
297+
expect(
298+
getValidDisplaySiblingNodeId({ next: nextNode, prev: null }),
299+
).toEqual(nextNode.id);
300+
expect(
301+
getValidDisplaySiblingNodeId({ next: null, prev: prevNode }),
302+
).toEqual(prevNode.id);
303+
expect(getValidDisplaySiblingNodeId({ next: null, prev: null })).toEqual(
304+
null,
305+
);
306+
});
307+
308+
test('should get is equal display sibling node id', () => {
309+
expect(
310+
isEqualDisplaySiblingNodeId(
311+
{ next: nextNode, prev: prevNode },
312+
nextNode.id,
313+
),
314+
).toBeTruthy();
315+
expect(
316+
isEqualDisplaySiblingNodeId(
317+
{ next: nextNode, prev: null },
318+
nextNode.id,
319+
),
320+
).toBeTruthy();
321+
expect(
322+
isEqualDisplaySiblingNodeId(
323+
{ next: null, prev: prevNode },
324+
prevNode.id,
325+
),
326+
).toBeTruthy();
327+
expect(
328+
isEqualDisplaySiblingNodeId({ next: null, prev: null }, nextNode.id),
329+
).toBeFalsy();
330+
});
331+
});
265332
});

packages/s2-core/src/cell/col-cell.ts

Lines changed: 112 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,38 @@
11
import { Point, SimpleBBox } from '@antv/g-canvas';
2-
import { shouldAddResizeArea } from './../utils/interaction/resize';
2+
import { isEmpty } from 'lodash';
3+
import { isEqualDisplaySiblingNodeId } from './../utils/hide-columns';
34
import { HeaderCell } from './header-cell';
4-
import {
5-
getResizeAreaAttrs,
6-
getOrCreateResizeAreaGroupById,
7-
} from '@/utils/interaction/resize';
5+
import { shouldAddResizeArea } from '@/utils/interaction/resize';
86
import {
97
CellTypes,
10-
KEY_GROUP_COL_RESIZE_AREA,
118
HORIZONTAL_RESIZE_AREA_KEY_PRE,
12-
ResizeDirectionType,
9+
KEY_GROUP_COL_RESIZE_AREA,
1310
ResizeAreaEffect,
11+
ResizeDirectionType,
12+
S2Event,
1413
} from '@/common/constant';
1514
import {
1615
CellBorderPosition,
16+
DefaultCellTheme,
1717
FormatResult,
18+
IconTheme,
1819
TextAlign,
1920
TextBaseline,
2021
TextTheme,
2122
} from '@/common/interface';
22-
import { ColHeaderConfig } from '@/facet/header/col';
23-
import { renderLine, renderRect } from '@/utils/g-renders';
2423
import { AreaRange } from '@/common/interface/scroll';
24+
import { ColHeaderConfig } from '@/facet/header/col';
2525
import {
26-
getTextAndIconPositionWhenHorizontalScrolling,
27-
getTextAndFollowingIconPosition,
2826
getBorderPositionAndStyle,
27+
getTextAndFollowingIconPosition,
28+
getTextAndIconPositionWhenHorizontalScrolling,
2929
} from '@/utils/cell/cell';
30+
import { renderIcon, renderLine, renderRect } from '@/utils/g-renders';
31+
import { isLastColumnAfterHidden } from '@/utils/hide-columns';
32+
import {
33+
getOrCreateResizeAreaGroupById,
34+
getResizeAreaAttrs,
35+
} from '@/utils/interaction/resize';
3036

3137
export class ColCell extends HeaderCell {
3238
protected headerConfig: ColHeaderConfig;
@@ -52,6 +58,7 @@ export class ColCell extends HeaderCell {
5258
// draw resize ares
5359
this.drawResizeArea();
5460
this.update();
61+
this.addExpandColumnIconShapes();
5562
}
5663

5764
protected drawBackgroundShape() {
@@ -333,4 +340,98 @@ export class ColCell extends HeaderCell {
333340
this.drawHorizontalBorder();
334341
this.drawVerticalBorder();
335342
}
343+
344+
protected hasHiddenColumnCell() {
345+
const {
346+
interaction: { hiddenColumnFields = [] },
347+
tooltip: { operation },
348+
} = this.spreadsheet.options;
349+
350+
const hiddenColumnsDetail = this.spreadsheet.store.get(
351+
'hiddenColumnsDetail',
352+
[],
353+
);
354+
355+
if (
356+
isEmpty(hiddenColumnsDetail) ||
357+
isEmpty(hiddenColumnFields) ||
358+
!operation.hiddenColumns
359+
) {
360+
return false;
361+
}
362+
return !!hiddenColumnsDetail.find((column) =>
363+
isEqualDisplaySiblingNodeId(column?.displaySiblingNode, this.meta.id),
364+
);
365+
}
366+
367+
private getExpandIconTheme(): IconTheme {
368+
const themeCfg = this.getStyle() as DefaultCellTheme;
369+
return themeCfg.icon;
370+
}
371+
372+
private addExpandColumnSplitLine() {
373+
const { x, y, width, height } = this.meta;
374+
const {
375+
horizontalBorderColor,
376+
horizontalBorderWidth,
377+
horizontalBorderColorOpacity,
378+
} = this.theme.splitLine;
379+
const lineX = this.isLastColumn() ? x + width - horizontalBorderWidth : x;
380+
381+
renderLine(
382+
this,
383+
{
384+
x1: lineX,
385+
y1: y,
386+
x2: lineX,
387+
y2: y + height,
388+
},
389+
{
390+
stroke: horizontalBorderColor,
391+
lineWidth: horizontalBorderWidth,
392+
strokeOpacity: horizontalBorderColorOpacity,
393+
},
394+
);
395+
}
396+
397+
private addExpandColumnIconShapes() {
398+
if (!this.hasHiddenColumnCell()) {
399+
return;
400+
}
401+
this.addExpandColumnSplitLine();
402+
this.addExpandColumnIcon();
403+
}
404+
405+
private addExpandColumnIcon() {
406+
const iconConfig = this.getExpandColumnIconConfig();
407+
const icon = renderIcon(this, {
408+
...iconConfig,
409+
name: 'ExpandColIcon',
410+
cursor: 'pointer',
411+
});
412+
icon.on('click', () => {
413+
this.spreadsheet.emit(S2Event.LAYOUT_TABLE_COL_EXPANDED, this.meta);
414+
});
415+
}
416+
417+
// 在隐藏的下一个兄弟节点的起始坐标显示隐藏提示线和展开按钮, 如果是尾元素, 则显示在前一个兄弟节点的结束坐标
418+
private getExpandColumnIconConfig() {
419+
const { size } = this.getExpandIconTheme();
420+
const { x, y, width, height } = this.getCellArea();
421+
422+
const baseIconX = x - size;
423+
const iconX = this.isLastColumn() ? baseIconX + width : baseIconX;
424+
const iconY = y + height / 2 - size / 2;
425+
426+
return {
427+
x: iconX,
428+
y: iconY,
429+
width: size * 2,
430+
height: size,
431+
};
432+
}
433+
434+
private isLastColumn() {
435+
return isLastColumnAfterHidden(this.spreadsheet, this.meta.id);
436+
}
336437
}

packages/s2-core/src/cell/table-col-cell.ts

Lines changed: 10 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
import { get, isEmpty, find } from 'lodash';
2-
import { isFrozenCol, isFrozenTrailingCol } from 'src/facet/utils';
3-
import { getExtraPaddingForExpandIcon } from 'src/utils/cell/table-col-cell';
4-
import { getContentArea } from 'src/utils/cell/cell';
5-
import { getSortTypeIcon } from 'src/utils/sort-action';
1+
import { find, get } from 'lodash';
62
import { Group } from '@antv/g-canvas';
7-
import { isLastColumnAfterHidden } from '@/utils/hide-columns';
8-
import { S2Event, HORIZONTAL_RESIZE_AREA_KEY_PRE } from '@/common/constant';
9-
import { renderIcon, renderLine, renderRect } from '@/utils/g-renders';
103
import { ColCell } from '@/cell/col-cell';
114
import {
12-
DefaultCellTheme,
13-
FormatResult,
14-
IconTheme,
15-
SortParam,
16-
} from '@/common/interface';
17-
import { KEY_GROUP_FROZEN_COL_RESIZE_AREA } from '@/common/constant';
5+
HORIZONTAL_RESIZE_AREA_KEY_PRE,
6+
KEY_GROUP_FROZEN_COL_RESIZE_AREA,
7+
} from '@/common/constant';
8+
import { FormatResult, SortParam } from '@/common/interface';
9+
import { isFrozenCol, isFrozenTrailingCol } from '@/facet/utils';
10+
import { getContentArea } from '@/utils/cell/cell';
11+
import { getExtraPaddingForExpandIcon } from '@/utils/cell/table-col-cell';
12+
import { renderRect } from '@/utils/g-renders';
1813
import { getOrCreateResizeAreaGroupById } from '@/utils/interaction/resize';
14+
import { getSortTypeIcon } from '@/utils/sort-action';
1915

2016
export class TableColCell extends ColCell {
2117
protected handleRestOptions(...[headerConfig]) {
@@ -71,31 +67,6 @@ export class TableColCell extends ColCell {
7167
return get(style, 'bolderText');
7268
}
7369

74-
protected initCell() {
75-
super.initCell();
76-
this.addExpandColumnIconShapes();
77-
}
78-
79-
private hasHiddenColumnCell() {
80-
const {
81-
interaction: { hiddenColumnFields = [] },
82-
tooltip: { operation },
83-
} = this.spreadsheet.options;
84-
85-
if (isEmpty(hiddenColumnFields) || !operation.hiddenColumns) {
86-
return false;
87-
}
88-
const hiddenColumnsDetail = this.spreadsheet.store.get(
89-
'hiddenColumnsDetail',
90-
[],
91-
);
92-
return !!hiddenColumnsDetail.find((column) => {
93-
const { prev, next } = column?.displaySiblingNode || {};
94-
const hiddenSiblingNode = next || prev;
95-
return hiddenSiblingNode?.field === this.meta?.field;
96-
});
97-
}
98-
9970
public getContentArea() {
10071
const { padding } = this.getStyle()?.cell || this.theme.dataCell.cell;
10172
const newPadding = { ...padding };
@@ -115,77 +86,6 @@ export class TableColCell extends ColCell {
11586
return getContentArea(this.getCellArea(), newPadding);
11687
}
11788

118-
private getExpandIconTheme(): IconTheme {
119-
const themeCfg = this.getStyle() as DefaultCellTheme;
120-
return themeCfg.icon;
121-
}
122-
123-
private addExpandColumnSplitLine() {
124-
const { x, y, width, height } = this.meta;
125-
const {
126-
horizontalBorderColor,
127-
horizontalBorderWidth,
128-
horizontalBorderColorOpacity,
129-
} = this.theme.splitLine;
130-
const lineX = this.isLastColumn() ? x + width - horizontalBorderWidth : x;
131-
132-
renderLine(
133-
this,
134-
{
135-
x1: lineX,
136-
y1: y,
137-
x2: lineX,
138-
y2: y + height,
139-
},
140-
{
141-
stroke: horizontalBorderColor,
142-
lineWidth: horizontalBorderWidth,
143-
strokeOpacity: horizontalBorderColorOpacity,
144-
},
145-
);
146-
}
147-
148-
private addExpandColumnIconShapes() {
149-
if (!this.hasHiddenColumnCell()) {
150-
return;
151-
}
152-
this.addExpandColumnSplitLine();
153-
this.addExpandColumnIcon();
154-
}
155-
156-
private addExpandColumnIcon() {
157-
const iconConfig = this.getExpandColumnIconConfig();
158-
const icon = renderIcon(this, {
159-
...iconConfig,
160-
name: 'ExpandColIcon',
161-
cursor: 'pointer',
162-
});
163-
icon.on('click', () => {
164-
this.spreadsheet.emit(S2Event.LAYOUT_TABLE_COL_EXPANDED, this.meta);
165-
});
166-
}
167-
168-
// 在隐藏的下一个兄弟节点的起始坐标显示隐藏提示线和展开按钮, 如果是尾元素, 则显示在前一个兄弟节点的结束坐标
169-
private getExpandColumnIconConfig() {
170-
const { size } = this.getExpandIconTheme();
171-
const { x, y, width, height } = this.getCellArea();
172-
173-
const baseIconX = x - size;
174-
const iconX = this.isLastColumn() ? baseIconX + width : baseIconX;
175-
const iconY = y + height / 2 - size / 2;
176-
177-
return {
178-
x: iconX,
179-
y: iconY,
180-
width: size * 2,
181-
height: size,
182-
};
183-
}
184-
185-
private isLastColumn() {
186-
return isLastColumnAfterHidden(this.spreadsheet, this.meta.field);
187-
}
188-
18989
protected getHorizontalResizeAreaName() {
19090
return `${HORIZONTAL_RESIZE_AREA_KEY_PRE}${'table-col-cell'}`;
19191
}

packages/s2-core/src/common/interface/basic.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ export interface ViewMeta {
360360
// rowId of cell
361361
rowId?: string;
362362
colId?: string;
363+
field?: string;
363364
[key: string]: any;
364365
}
365366

0 commit comments

Comments
 (0)