Skip to content

Commit

Permalink
Merge pull request VisActor#2042 from VisActor/feat/pivot-pref
Browse files Browse the repository at this point in the history
Feat/pivot pref
  • Loading branch information
Rui-Sun authored Jul 12, 2024
2 parents a346932 + 1940622 commit 82cb9f5
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 57 deletions.
1 change: 1 addition & 0 deletions packages/vtable/src/core/utils/get-cell-position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ export function getCellAtRelativePosition(x: number, y: number, _this: BaseTable
bottomFrozen,
_this
);

if (colInfo && rowInfo) {
const { row, top, bottom, height } = rowInfo;
const { col, left, right, width } = colInfo;
Expand Down
7 changes: 5 additions & 2 deletions packages/vtable/src/dataset/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
typeSort
} from './statistics-helper';
import { IndicatorDimensionKeyPlaceholder } from '../tools/global';
import { join } from '../tools/join';
/**
* 数据处理模块
*/
Expand Down Expand Up @@ -994,7 +995,8 @@ export class Dataset {
}
});
}
flatRowKey = rowKey.join(this.stringJoinChar);
// flatRowKey = rowKey.join(this.stringJoinChar);
flatRowKey = join(rowKey, this.stringJoinChar);
}

if (typeof colKey === 'string') {
Expand All @@ -1008,7 +1010,8 @@ export class Dataset {
}
});
}
flatColKey = colKey.join(this.stringJoinChar);
// flatColKey = colKey.join(this.stringJoinChar);
flatColKey = join(colKey, this.stringJoinChar);
}
//TODO 原有逻辑 但这里先强制跳过
// if ( rowKey.length === 0 && colKey.length === 0) {
Expand Down
166 changes: 132 additions & 34 deletions packages/vtable/src/layout/pivot-header-layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,19 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
_chartItemBandSize: number;
_chartPadding?: number | number[];

_lastCellCol: number;
_lastCellRow: number;
_lastCellHeaderPath: IPivotTableCellHeaderPaths;

rowSeriesNumberColumn: SeriesNumberColumnData[];
leftRowSeriesNumberColumn: SeriesNumberColumnData[];
leftRowSeriesNumberColumnCount: number = 0;
rightRowSeriesNumberColumn: SeriesNumberColumnData[];
rightRowSeriesNumberColumnCount: number = 0;
//#endregion

_useGetBodyCache: boolean = false;
_getBodyCache: Map<number, IndicatorData | SeriesNumberColumnData> = new Map();

_useHeaderPathCache: boolean = false;
_colHeaderPathCache: Map<number, ITreeLayoutHeadNode[]> = new Map();
_rowHeaderPathCache: Map<number, ITreeLayoutHeadNode[]> = new Map();
constructor(
table: PivotTable | PivotChart,
dataset: Dataset,
Expand Down Expand Up @@ -1700,8 +1703,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
}
//TODO 这里的indicators是否可以改为和真正指标值一样数量 但目前也不会造成太多内存浪费 对象较简单 引用对象
getBody(_col: number, _row: number): IndicatorData | SeriesNumberColumnData {
const cache = this.getBodyWidthCache(_col, _row);
if (cache) {
return cache;
}
if (this.isSeriesNumber(_col, _row)) {
return this.getSeriesNumberBody(_col, _row);
const body = this.getSeriesNumberBody(_col, _row);
this.setBodyWidthCache(_col, _row, body);
return body;
}
// let indicatorData;
//正常情况下 通过行号或者列号可以取到Indicator的配置信息 但如果指标在前维度在后的情况下(如风神:列配置【指标名称,地区】) indicators中的数量是和真正指标值一样数量
Expand All @@ -1711,40 +1720,44 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
const paths = this.getCellHeaderPaths(_col, _row);
if (this.indicatorsAsCol) {
const indicatorKey = paths.colHeaderPaths?.find(colPath => colPath.indicatorKey)?.indicatorKey;
return isValid(indicatorKey)
const body = isValid(indicatorKey)
? this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ??
this._indicators[0] ?? {
id: '',
field: undefined,
indicatorKey: undefined,
cellType: 'text',
define: undefined
}
: {
this._indicators[0] ?? {
id: '',
field: undefined,
indicatorKey: undefined,
cellType: 'text',
define: undefined
};
}
const indicatorKey = paths.rowHeaderPaths?.find(rowPath => rowPath.indicatorKey)?.indicatorKey;
return isValid(indicatorKey)
? this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ??
this._indicators[0] ?? {
}
: ({
id: '',
field: undefined,
indicatorKey: undefined,
cellType: 'text',
define: undefined
}
: {
} as IndicatorData);
this.setBodyWidthCache(_col, _row, body);
return body;
}
const indicatorKey = paths.rowHeaderPaths?.find(rowPath => rowPath.indicatorKey)?.indicatorKey;
const body = isValid(indicatorKey)
? this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ??
this._indicators[0] ?? {
id: '',
field: undefined,
indicatorKey: undefined,
cellType: 'text',
define: undefined
};
}
: ({
id: '',
field: undefined,
indicatorKey: undefined,
cellType: 'text',
define: undefined
} as IndicatorData);
this.setBodyWidthCache(_col, _row, body);
return body;
}
// getBodyLayoutRangeById(id: LayoutObjectId): CellRange {
// for (let col = 0; col < (this.colCount ?? 0); col++) {
Expand Down Expand Up @@ -1917,9 +1930,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
// if (this._CellHeaderPathMap.has(`${col}-${row}`)) {
// return this._CellHeaderPathMap.get(`${col}-${row}`);
// }
if (col === this._lastCellCol && row === this._lastCellRow) {
return this._lastCellHeaderPath;
}
// if (col === this._lastCellCol && row === this._lastCellRow) {
// return this._lastCellHeaderPath;
// }

let _largeCellRangeCacheIndex = -1;
for (let i = 0; i < this._largeCellRangeCache.length; i++) {
const range = this._largeCellRangeCache[i];
Expand All @@ -1928,6 +1942,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
break;
}
}

let colPath: ITreeLayoutHeadNode[] = this.getColHeaderPathCache(col, row);
let rowPath: ITreeLayoutHeadNode[] = this.getRowHeaderPathCache(col, row);

// if (_largeCellRangeCacheIndex !== -1) {
// const range = this._largeCellRangeCache[_largeCellRangeCacheIndex];
// if (this._CellHeaderPathMap.has(`${range.start.col}-${range.start.row}`)) {
Expand All @@ -1937,17 +1955,22 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
// console.log(`${col}-${row}`);
const recordCol = this.getBodyIndexByCol(col);
const recordRow = this.getBodyIndexByRow(row) + this.currentPageStartIndex;
let colPath: ITreeLayoutHeadNode[] = [];
let rowPath: ITreeLayoutHeadNode[] = [];
if (row >= 0 && recordCol >= 0) {

// column
if (!colPath && row >= 0 && recordCol >= 0) {
colPath = this.columnDimensionTree.getTreePath(
recordCol,
this.showHeader && this.showColumnHeader
? row - (this.columnHeaderTitle ? 1 : 0)
: this.columnDimensionTree.totalLevel
);
// this._colHeaderPathCache.set(col, colPath);
this.setColHeaderPathCache(col, row, colPath);
}
if (col >= 0 && recordRow >= 0) {

// row
if (!rowPath && col >= 0 && recordRow >= 0) {
rowPath = [];
if (this.rowHierarchyType === 'tree') {
// 注释了原有逻辑
// if (col >= this.rowHeaderLevelCount) {
Expand Down Expand Up @@ -1978,7 +2001,8 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
}
// 组装好pathIds后从树中找出具体路径paths
const findedRowPath = findTree.getTreePathByCellIds(pathIds);
rowPath = rowPath.concat(findedRowPath);
// rowPath = rowPath.concat(findedRowPath);
rowPath.push(...findedRowPath);
findTree = this._rowHeaderExtensionTree[row_pathIds[level]];
level++;
}
Expand All @@ -1990,12 +2014,11 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
: this.rowDimensionTree.totalLevel
);
}
// this._rowHeaderPathCache.set(row, rowPath);
this.setRowHeaderPathCache(col, row, rowPath);
}
const p = { colHeaderPaths: colPath, rowHeaderPaths: rowPath, cellLocation: this.getCellLocation(col, row) };
// this._CellHeaderPathMap.set(`${col}-${row}`, p);
this._lastCellHeaderPath = p;
this._lastCellCol = col;
this._lastCellRow = row;
return p;
}
getCellHeaderPaths(col: number, row: number): IPivotTableCellHeaderPaths {
Expand Down Expand Up @@ -3664,6 +3687,81 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI {
}
}
}
enableUseGetBodyCache() {
this._useGetBodyCache = true;
this._getBodyCache.clear();
}
disableUseGetBodyCache() {
this._useGetBodyCache = false;
this._getBodyCache.clear();
}
enableUseHeaderPathCache() {
this._useHeaderPathCache = true;
this._colHeaderPathCache.clear();
this._rowHeaderPathCache.clear();
}
disableUseHeaderPathCache() {
this._useHeaderPathCache = false;
this._colHeaderPathCache.clear();
this._rowHeaderPathCache.clear();
}
getBodyWidthCache(col: number, row: number) {
if (!this._useGetBodyCache || this.isHeader(col, row) || this.isSeriesNumber(col, row)) {
return undefined;
}
if (this.indicatorsAsCol && this._getBodyCache.has(col)) {
return this._getBodyCache.get(col);
} else if (!this.indicatorsAsCol && this._getBodyCache.has(row)) {
return this._getBodyCache.get(row);
}
return undefined;
}
setBodyWidthCache(col: number, row: number, cache: IndicatorData | SeriesNumberColumnData) {
if (!this._useGetBodyCache || this.isHeader(col, row) || this.isSeriesNumber(col, row)) {
return;
}
if (this.indicatorsAsCol) {
this._getBodyCache.set(col, cache);
} else {
this._getBodyCache.set(row, cache);
}
}

getColHeaderPathCache(col: number, row: number) {
if (
this._useHeaderPathCache &&
!this.isHeader(col, row) &&
!this.isSeriesNumber(col, row) &&
this._colHeaderPathCache.has(col)
) {
return this._colHeaderPathCache.get(col);
}
return undefined;
}

setColHeaderPathCache(col: number, row: number, cache: ITreeLayoutHeadNode[]) {
if (this._useHeaderPathCache && !this.isHeader(col, row) && !this.isSeriesNumber(col, row)) {
this._colHeaderPathCache.set(col, cache);
}
}

getRowHeaderPathCache(col: number, row: number) {
if (
this._useHeaderPathCache &&
!this.isHeader(col, row) &&
!this.isSeriesNumber(col, row) &&
this._rowHeaderPathCache.has(row)
) {
return this._rowHeaderPathCache.get(row);
}
return undefined;
}

setRowHeaderPathCache(col: number, row: number, cache: ITreeLayoutHeadNode[]) {
if (this._useHeaderPathCache && !this.isHeader(col, row) && !this.isSeriesNumber(col, row)) {
this._rowHeaderPathCache.set(row, cache);
}
}
}
/** 计算 scale 的实际 range 长度 */
function scaleWholeRangeSize(count: number, bandwidth: number, paddingInner: number, paddingOuter: number) {
Expand Down
27 changes: 19 additions & 8 deletions packages/vtable/src/scenegraph/layout/compute-col-width.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?
// }
}

const layoutMap = table.internalProps.layoutMap;
if (table.isPivotTable()) {
(layoutMap as PivotHeaderLayoutMap).enableUseGetBodyCache();
(layoutMap as PivotHeaderLayoutMap).enableUseHeaderPathCache();
}

const oldColWidths: number[] = [];
const newWidths: number[] = [];
if (update) {
Expand Down Expand Up @@ -95,7 +101,7 @@ export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?
let endCol = table.colCount;
if (table.widthAdaptiveMode === 'only-body') {
for (let col = 0; col < table.colCount; col++) {
const colWidth = update ? newWidths[col] : table.getColWidth(col);
const colWidth = update ? newWidths[col] ?? table.getColWidth(col) : table.getColWidth(col);
if (
col < table.rowHeaderLevelCount ||
(table.isPivotChart() && col >= table.colCount - table.rightFrozenColCount)
Expand Down Expand Up @@ -146,7 +152,7 @@ export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?
let actualHeaderWidth = 0;
let actualWidth = 0;
for (let col = 0; col < table.colCount; col++) {
const colWidth = update ? newWidths[col] : table.getColWidth(col);
const colWidth = update ? newWidths[col] ?? table.getColWidth(col) : table.getColWidth(col);
if (
col < table.rowHeaderLevelCount ||
(table.isPivotChart() && col >= table.colCount - table.rightFrozenColCount)
Expand Down Expand Up @@ -198,7 +204,7 @@ export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?
for (let col = 0; col < table.colCount; col++) {
// newColWidth could not be in column min max range possibly
// const newColWidth = table._adjustColWidth(col, newWidths[col]) ?? table.getColWidth(col);
const newColWidth = newWidths[col] ?? table.getColWidth(col);
const newColWidth = newWidths[col] ?? table.getColWidth(col) ?? table.getColWidth(col);
if (newColWidth !== oldColWidths[col]) {
// update the column width in scenegraph
table._setColWidth(col, newColWidth, false, true);
Expand All @@ -219,6 +225,11 @@ export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?
table.scenegraph.updateContainer(true);
}
// console.log('computeColsWidth time:', (typeof window !== 'undefined' ? window.performance.now() : 0) - time, colStart, colEnd);

if (table.isPivotTable()) {
(layoutMap as PivotHeaderLayoutMap).disableUseGetBodyCache();
(layoutMap as PivotHeaderLayoutMap).disableUseHeaderPathCache();
}
}

/**
Expand Down Expand Up @@ -374,7 +385,7 @@ function computeAutoColWidth(
cellHierarchyIndent += table.internalProps.headerHelper.getHierarchyIconWidth();
}
}
} else {
} else if (table.isListTable()) {
deltaRow = prepareDeltaRow;
// 基本表格表身body单元格 如果是树形展开 需要考虑缩进值
// const cellHierarchyState = table.getHierarchyState(col, row);
Expand Down Expand Up @@ -595,7 +606,7 @@ function computeTextWidth(col: number, row: number, cellType: ColumnTypeOption,
text = cellValue;
}
const lines = breakString(text, table).text;
if (lines.length >= 1) {
if (lines.length >= 1 && !(lines.length === 1 && lines[0] === '')) {
// eslint-disable-next-line no-loop-func
lines.forEach((line: string) => {
const width = table.measureText(line, {
Expand Down Expand Up @@ -696,7 +707,7 @@ export function getAdaptiveWidth(
const sparklineColumns = [];
let totalSparklineAbleWidth = 0;
for (let col = startCol; col < endColPlus1; col++) {
const width = update ? newWidths[col] : table.getColWidth(col);
const width = update ? newWidths[col] ?? table.getColWidth(col) : table.getColWidth(col);
const maxWidth = table.getMaxColWidth(col);
const minWidth = table.getMinColWidth(col);
if (width !== maxWidth && width !== minWidth) {
Expand Down Expand Up @@ -748,12 +759,12 @@ export function getAdaptiveWidth(
totalDrawWidth -
adaptiveColumns.reduce((acr, cur, index) => {
if (cur !== col) {
return acr + (update ? newWidths[cur] : table.getColWidth(cur));
return acr + (update ? newWidths[cur] ?? table.getColWidth(col) : table.getColWidth(cur));
}
return acr;
}, 0);
} else {
colWidth = Math.round((update ? newWidths[col] : table.getColWidth(col)) * factor);
colWidth = Math.round((update ? newWidths[col] ?? table.getColWidth(col) : table.getColWidth(col)) * factor);
}
if (update) {
newWidths[col] = table._adjustColWidth(col, colWidth);
Expand Down
Loading

0 comments on commit 82cb9f5

Please sign in to comment.