diff --git a/common/changes/@visactor/vtable/3653-feature-pivotTable-corner_2025-04-01-08-01.json b/common/changes/@visactor/vtable/3653-feature-pivotTable-corner_2025-04-01-08-01.json new file mode 100644 index 0000000000..fdf2813df7 --- /dev/null +++ b/common/changes/@visactor/vtable/3653-feature-pivotTable-corner_2025-04-01-08-01.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "feat: refactor pivotTable corner with no columns or rows case #3653\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-selected-border-update_2025-03-28-08-48.json b/common/changes/@visactor/vtable/fix-selected-border-update_2025-03-28-08-48.json new file mode 100644 index 0000000000..e0ad5a0761 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-selected-border-update_2025-03-28-08-48.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add dynamicUpdateSelectionSize config in theme.selectionStyle", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index e0c4ea6c3c..55c32ae803 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -1163,6 +1163,9 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { height - ((lineWidths[0] ?? 0) + (shadowWidths[0] ?? 0)) - ((lineWidths[2] ?? 0) + (shadowWidths[2] ?? 0)); } } + + this._clearColRangeWidthsMap(); + this._clearRowRangeHeightsMap(); } updateViewBox(newViewBox: IBoundsLike) { diff --git a/packages/vtable/src/core/tableHelper.ts b/packages/vtable/src/core/tableHelper.ts index 1a41bccd9c..c8695a2ef1 100644 --- a/packages/vtable/src/core/tableHelper.ts +++ b/packages/vtable/src/core/tableHelper.ts @@ -368,25 +368,43 @@ export function getCellCornerRadius(col: number, row: number, table: BaseTableAP const tableCornerRadius = table.theme.frameStyle.cornerRadius; if (table.theme.cellInnerBorder) { if (Array.isArray(tableCornerRadius)) { + const radius = [0, 0, 0, 0]; if (col === 0 && row === 0) { - return [tableCornerRadius[0], 0, 0, 0]; - } else if (col === table.colCount - 1 && row === 0) { - return [0, tableCornerRadius[1], 0, 0]; - } else if (col === 0 && row === table.rowCount - 1) { - return [0, 0, 0, tableCornerRadius[3]]; - } else if (col === table.colCount - 1 && row === table.rowCount - 1) { - return [0, 0, tableCornerRadius[2], 0]; + // return [tableCornerRadius[0], 0, 0, 0]; + radius[0] = tableCornerRadius[0]; } + if (col === table.colCount - 1 && row === 0) { + // return [0, tableCornerRadius[1], 0, 0]; + radius[1] = tableCornerRadius[1]; + } + if (col === 0 && row === table.rowCount - 1) { + // return [0, 0, 0, tableCornerRadius[3]]; + radius[3] = tableCornerRadius[3]; + } + if (col === table.colCount - 1 && row === table.rowCount - 1) { + // return [0, 0, tableCornerRadius[2], 0]; + radius[2] = tableCornerRadius[2]; + } + return radius; } else if (tableCornerRadius) { + const radius = [0, 0, 0, 0]; if (col === 0 && row === 0) { - return [tableCornerRadius, 0, 0, 0]; - } else if (col === table.colCount - 1 && row === 0) { - return [0, tableCornerRadius, 0, 0]; - } else if (col === 0 && row === table.rowCount - 1) { - return [0, 0, 0, tableCornerRadius]; - } else if (col === table.colCount - 1 && row === table.rowCount - 1) { - return [0, 0, tableCornerRadius, 0]; + // return [tableCornerRadius, 0, 0, 0]; + radius[0] = tableCornerRadius; + } + if (col === table.colCount - 1 && row === 0) { + // return [0, tableCornerRadius, 0, 0]; + radius[1] = tableCornerRadius; + } + if (col === 0 && row === table.rowCount - 1) { + // return [0, 0, 0, tableCornerRadius]; + radius[3] = tableCornerRadius; + } + if (col === table.colCount - 1 && row === table.rowCount - 1) { + // return [0, 0, tableCornerRadius, 0]; + radius[2] = tableCornerRadius; } + return radius; } } return 0; diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 4998086d7e..007bb98f84 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -798,6 +798,9 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHierarchyType === 'grid-tree' ? this._getRowHeaderTreeExpandedMaxLevelCount() || this.rowHeaderLevelCount : this.rowHeaderLevelCount; + if (colLevelCount === 0 || rowLevelCount === 0) { + return results; + } if (this.cornerSetting.titleOnDimension === 'all') { if (this.indicatorsAsCol) { if (colDimensionKeys) { @@ -1581,7 +1584,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { !this.dataset.customColTree?.length //根据情况来加的判断条件 之前是只兼容没有设置两个自定义树的情况 现在对有自定义树的情况也处理出现角头 // && !this.dataset.customRowTree?.length ) { - if (this.cornerSetting.titleOnDimension === 'row' && this.cornerSetting.forceShowHeader) { + if ( + (this.cornerSetting.titleOnDimension === 'row' || this.cornerSetting.titleOnDimension === 'all') && + this.cornerSetting.forceShowHeader + ) { count = 1; } else if ( !this._table.isPivotChart() && @@ -1658,7 +1664,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // && !this.dataset.customColTree !this.dataset.customRowTree?.length //根据情况来加的判断条件 之前是只兼容没有设置两个自定义树的情况 现在对有自定义树的情况也处理出现角头 ) { - if (this.cornerSetting.titleOnDimension === 'column' && this.cornerSetting.forceShowHeader) { + if ( + (this.cornerSetting.titleOnDimension === 'column' || this.cornerSetting.titleOnDimension === 'all') && + this.cornerSetting.forceShowHeader + ) { count = 1; } else if ( !this._table.isPivotChart() && @@ -1714,17 +1723,20 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this._rowHeaderLevelCount = count; } get colCount(): number { - return ( - (this._getColumnHeaderTreeExpandedMaxLevelCount() > 0 || + let bodyColCount; + if ( + this._getColumnHeaderTreeExpandedMaxLevelCount() > 0 || this._table.isPivotChart() || (this.dataset.records as Array)?.length > 0 || (this.dataset.records && !Array.isArray(this.dataset.records)) - ? this._columnHeaderCellIds[0]?.length ?? this.columnDimensionTree.tree.size - : 0) + - this.rowHeaderLevelCount + - this.rightHeaderColCount + - this.leftRowSeriesNumberColumnCount - ); // 小心rightFrozenColCount和colCount的循环引用 造成调用栈溢出 + ) { + bodyColCount = + (this._columnHeaderCellIds[0]?.length ?? this.columnDimensionTree.tree.size) || + (this._indicators?.length > 0 ? 1 : 0); + } else { + bodyColCount = 0; + } + return bodyColCount + this.rowHeaderLevelCount + this.rightHeaderColCount + this.leftRowSeriesNumberColumnCount; // 小心rightFrozenColCount和colCount的循环引用 造成调用栈溢出 } get rowCount(): number { return ( @@ -1740,7 +1752,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.columnHeaderLevelCount + this.bottomHeaderRowCount // 小心bottomFrozenRowCount和rowCount的循环引用 造成调用栈溢出 ); - // return (this._rowHeaderCellIds?.length ?? 0) + this.columnHeaderLevelCount + this.bottomFrozenRowCount; } get bodyRowSpanCount() { return this.rowDimensionTree.tree.size; diff --git a/packages/vtable/src/layout/tree-helper.ts b/packages/vtable/src/layout/tree-helper.ts index 054afadaa6..8802e553e8 100644 --- a/packages/vtable/src/layout/tree-helper.ts +++ b/packages/vtable/src/layout/tree-helper.ts @@ -169,7 +169,7 @@ export class DimensionTree { size += this.setTreeNode(n, size, node); }); } else { - size = 1; + node.level === -1 ? (size = 0) : (size = 1); // re.totalLevel = Math.max(re.totalLevel, (node.level ?? -1) + 1); } } else if (node.hierarchyState === HierarchyState.expand && children?.length >= 1) { @@ -224,7 +224,7 @@ export class DimensionTree { } else { //树形展示 无children子节点。但不能确定是最后一层的叶子节点 totalLevel还不能确定是计算完整棵树的整体深度 node.hierarchyState = HierarchyState.none; - size = 1; + node.level === -1 ? (size = 0) : (size = 1); } node.size = size; diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index c598986167..65f288fa19 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -1233,8 +1233,10 @@ export class Scenegraph { */ setBodyAndRowHeaderY(y: number) { // correct y, avoid scroll out of range - const firstBodyCell = this.bodyGroup.firstChild?.firstChild as Group; - const lastBodyCell = this.bodyGroup.firstChild?.lastChild as Group; + const firstBodyCell = + (this.bodyGroup.firstChild?.firstChild as Group) ?? (this.rowHeaderGroup.firstChild?.firstChild as Group); + const lastBodyCell = + (this.bodyGroup.firstChild?.lastChild as Group) ?? (this.rowHeaderGroup.firstChild?.lastChild as Group); if ( y === 0 && firstBodyCell && diff --git a/packages/vtable/src/scenegraph/select/update-select-border.ts b/packages/vtable/src/scenegraph/select/update-select-border.ts index 913aeaa3cc..229e627a1f 100644 --- a/packages/vtable/src/scenegraph/select/update-select-border.ts +++ b/packages/vtable/src/scenegraph/select/update-select-border.ts @@ -153,11 +153,12 @@ function updateComponent( } } + const { dynamicUpdateSelectionSize } = table.theme.selectionStyle; if ( - (isNearRowHeader && selectComp.rect.attribute.stroke[3]) || - (isNearRightRowHeader && selectComp.rect.attribute.stroke[1]) || - (isNearColHeader && selectComp.rect.attribute.stroke[0]) || - (isNearBottomColHeader && selectComp.rect.attribute.stroke[2]) + (isNearRowHeader && (selectComp.rect.attribute.stroke[3] || dynamicUpdateSelectionSize)) || + (isNearRightRowHeader && (selectComp.rect.attribute.stroke[1] || dynamicUpdateSelectionSize)) || + (isNearColHeader && (selectComp.rect.attribute.stroke[0] || dynamicUpdateSelectionSize)) || + (isNearBottomColHeader && (selectComp.rect.attribute.stroke[2] || dynamicUpdateSelectionSize)) ) { if (isNearRowHeader && selectComp.rect.attribute.stroke[3]) { scene.tableGroup.insertAfter( diff --git a/packages/vtable/src/themes/theme.ts b/packages/vtable/src/themes/theme.ts index 5f5d42f438..94004a960a 100644 --- a/packages/vtable/src/themes/theme.ts +++ b/packages/vtable/src/themes/theme.ts @@ -719,6 +719,9 @@ export class TableTheme implements ITableThemeDefine { }, get selectionFillMode(): 'overlay' | 'replace' { return selectionStyle?.selectionFillMode ?? 'overlay'; + }, + get dynamicUpdateSelectionSize(): boolean { + return selectionStyle?.dynamicUpdateSelectionSize ?? false; } }; } diff --git a/packages/vtable/src/ts-types/theme.ts b/packages/vtable/src/ts-types/theme.ts index 87a0924630..9c9f22fc57 100644 --- a/packages/vtable/src/ts-types/theme.ts +++ b/packages/vtable/src/ts-types/theme.ts @@ -154,6 +154,7 @@ export interface ITableThemeDefine { inlineRowBgColor?: string; //交互所在整行的背景颜色 inlineColumnBgColor?: string; //交互所在整列的背景颜色 selectionFillMode?: 'overlay' | 'replace'; //选择框填充模式,overlay表示选择框背景色覆盖在表格上(需要配饰透明度),replace表示背景色替换原有单元格的背景色 + dynamicUpdateSelectionSize?: boolean; // 选择框大小随滚动动态变化,用于冻结并且背景透明的场景,默认false,开启后性能会有一定影响 }; // style for axis