From b1779e908c50ba4c7fb2635ba3da601ee29a42bb Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 16 Aug 2023 11:00:34 +0800 Subject: [PATCH 1/3] refactor: optimize chart rerender times when click mark state isn't change --- packages/vtable/src/event/drill.ts | 20 ++++++++- packages/vtable/src/event/event.ts | 5 ++- .../src/event/pivot-chart/axis-click.ts | 5 ++- packages/vtable/src/layout/pivot-layout.ts | 4 +- .../vtable/src/scenegraph/graphic/chart.ts | 1 - .../scenegraph/refresh-node/update-chart.ts | 20 +++++---- packages/vtable/src/scenegraph/scenegraph.ts | 2 +- .../vtable/src/state/hover/update-position.ts | 3 +- packages/vtable/src/tools/util.ts | 42 +++++++++++++++++++ 9 files changed, 83 insertions(+), 19 deletions(-) diff --git a/packages/vtable/src/event/drill.ts b/packages/vtable/src/event/drill.ts index 607551ea7..636b34f4b 100644 --- a/packages/vtable/src/event/drill.ts +++ b/packages/vtable/src/event/drill.ts @@ -1,6 +1,6 @@ import { TABLE_EVENT_TYPE } from '../core/TABLE_EVENT_TYPE'; import type { PivotHeaderLayoutMap } from '../layout/pivot-header-layout'; -import type { DrillMenuEventInfo, MousePointerCellEvent } from '../ts-types'; +import type { DrillMenuEventInfo, MousePointerCellEvent, PivotTableAPI } from '../ts-types'; import type { BaseTableAPI } from '../ts-types/base-table'; import { PIVOT_TABLE_EVENT_TYPE } from '../ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; @@ -33,3 +33,21 @@ export function bindDrillEvent(table: BaseTableAPI) { export function drillClick(table: BaseTableAPI) { table.fireListeners(PIVOT_TABLE_EVENT_TYPE.DRILLMENU_CLICK, table.stateManeger.drill as DrillMenuEventInfo); } + +export function checkHaveDrill(table: PivotTableAPI) { + const rowsDefine = (table.internalProps.layoutMap as PivotHeaderLayoutMap).rowsDefine; + const columnsDefine = (table.internalProps.layoutMap as PivotHeaderLayoutMap).columnsDefine; + for (let i = 0; i < rowsDefine.length; i++) { + const row = rowsDefine[i]; + if (typeof row !== 'string' && (row.drillDown || row.drillUp)) { + return true; + } + } + for (let i = 0; i < columnsDefine.length; i++) { + const column = columnsDefine[i]; + if (typeof column !== 'string' && (column.drillDown || column.drillUp)) { + return true; + } + } + return false; +} diff --git a/packages/vtable/src/event/event.ts b/packages/vtable/src/event/event.ts index d0e20a833..065971ed3 100644 --- a/packages/vtable/src/event/event.ts +++ b/packages/vtable/src/event/event.ts @@ -9,7 +9,7 @@ import { TABLE_EVENT_TYPE } from '../core/TABLE_EVENT_TYPE'; import type { Icon } from '../scenegraph/graphic/icon'; import { checkCellInSelect } from '../state/common/check-in-select'; import { bindMediaClick } from './media-click'; -import { bindDrillEvent, drillClick } from './drill'; +import { bindDrillEvent, checkHaveDrill, drillClick } from './drill'; import { bindSparklineHoverEvent } from './sparkline-event'; import type { BaseTableAPI } from '../ts-types/base-table'; import { checkHaveTextStick, handleTextStick } from '../scenegraph/stick-text'; @@ -20,6 +20,7 @@ import { bindTouchListener } from './listener/touch'; import { getCellEventArgsSet, type SceneEvent } from './util'; import { bindAxisClickEvent } from './pivot-chart/axis-click'; import { bindAxisHoverEvent } from './pivot-chart/axis-hover'; +import type { PivotTable } from '../PivotTable'; export class EventManeger { table: BaseTableAPI; @@ -102,7 +103,7 @@ export class EventManeger { }); // drill icon - if (this.table.isPivotTable()) { + if (this.table.isPivotTable() && checkHaveDrill(this.table as PivotTable)) { bindDrillEvent(this.table); } diff --git a/packages/vtable/src/event/pivot-chart/axis-click.ts b/packages/vtable/src/event/pivot-chart/axis-click.ts index 0681164f3..37b92ae9d 100644 --- a/packages/vtable/src/event/pivot-chart/axis-click.ts +++ b/packages/vtable/src/event/pivot-chart/axis-click.ts @@ -12,6 +12,9 @@ export function bindAxisClickEvent(table: BaseTableAPI) { } table.scenegraph.tableGroup.addEventListener('click', (e: FederatedPointerEvent) => { + if (table.stateManeger.columnMove.moving || table.stateManeger.columnResize.resizing) { + return; + } if (e.target.name === 'axis-label') { const eventArgsSet: SceneEvent = getCellEventArgsSet(e); const { col, row } = eventArgsSet.eventArgs; @@ -52,7 +55,7 @@ export function bindAxisClickEvent(table: BaseTableAPI) { // 清除chart缓存图片 clearChartCacheImage(table.scenegraph); table.scenegraph.updateNextFrame(); - } else if ((table as PivotChart)._selectedDimensionInChart) { + } else if ((table as PivotChart)._selectedDimensionInChart?.length) { (table as PivotChart)._selectedDimensionInChart.length = 0; const layout = table.internalProps.layoutMap as PivotLayoutMap; layout.updateDataStateToChartInstance(); diff --git a/packages/vtable/src/layout/pivot-layout.ts b/packages/vtable/src/layout/pivot-layout.ts index 84c791626..5c763b165 100644 --- a/packages/vtable/src/layout/pivot-layout.ts +++ b/packages/vtable/src/layout/pivot-layout.ts @@ -1383,7 +1383,7 @@ export class PivotLayoutMap implements LayoutMapAPI { return true; }); return !!match; - } else if ((this._table as PivotChart)._selectedDimensionInChart.length) { + } else if ((this._table as PivotChart)._selectedDimensionInChart?.length) { // 判断维度点击 const match = (this._table as PivotChart)._selectedDimensionInChart.every(item => { if (datum[item.key] !== item.value) { @@ -1408,7 +1408,7 @@ export class PivotLayoutMap implements LayoutMapAPI { return true; }); return !match; - } else if ((this._table as PivotChart)._selectedDimensionInChart.length) { + } else if ((this._table as PivotChart)._selectedDimensionInChart?.length) { // 判断维度点击 const match = (this._table as PivotChart)._selectedDimensionInChart.every(item => { if (datum[item.key] !== item.value) { diff --git a/packages/vtable/src/scenegraph/graphic/chart.ts b/packages/vtable/src/scenegraph/graphic/chart.ts index 21ef2ea30..cca6f72f7 100644 --- a/packages/vtable/src/scenegraph/graphic/chart.ts +++ b/packages/vtable/src/scenegraph/graphic/chart.ts @@ -3,7 +3,6 @@ import { genNumberType, Group } from '@visactor/vrender'; import { Bounds, cloneDeep } from '@visactor/vutils'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { PivotChart } from '../../PivotChart'; -import { clearChartCacheImage, updateChartSize } from '../refresh-node/update-chart'; import type { PivotLayoutMap } from '../../layout/pivot-layout'; interface IChartGraphicAttribute extends IGroupGraphicAttribute { diff --git a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts index 46b755ccc..df3f67016 100644 --- a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts +++ b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts @@ -1,6 +1,7 @@ import type { PivotChart } from '../../PivotChart'; import { CartesianAxis } from '../../components/axis/axis'; import type { PivotLayoutMap } from '../../layout/pivot-layout'; +import { compareArrays } from '../../tools/util'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { Chart } from '../graphic/chart'; import type { Group } from '../graphic/group'; @@ -119,7 +120,8 @@ export function updateChartState(scenegraph: Scenegraph, datum: any) { //避免无效的更新 return; } - (table as PivotChart)._selectedDataItemsInChart = []; + // (table as PivotChart)._selectedDataItemsInChart = []; + const newSelectedDataItemsInChart = []; if (Array.isArray(datum)) { datum.forEach((dataItem: any) => { if (dataItem && dataItem.key !== 0 && Object.keys(dataItem).length > 0) { @@ -130,7 +132,7 @@ export function updateChartState(scenegraph: Scenegraph, datum: any) { selectedState[itemKey] = dataItem[itemKey]; } } - (table as PivotChart)._selectedDataItemsInChart.push(selectedState); + newSelectedDataItemsInChart.push(selectedState); } }); } else if (datum && datum.key !== 0 && Object.keys(datum).length > 0) { @@ -141,16 +143,16 @@ export function updateChartState(scenegraph: Scenegraph, datum: any) { selectedState[itemKey] = datum[itemKey]; } } - (table as PivotChart)._selectedDataItemsInChart.push(selectedState); + newSelectedDataItemsInChart.push(selectedState); } //避免无效的更新 - if ((table as PivotChart)._selectedDataItemsInChart.length === 0 && preSelectItemsCount === 0) { - return; + if (!compareArrays((table as PivotChart)._selectedDataItemsInChart, newSelectedDataItemsInChart)) { + (table as PivotChart)._selectedDataItemsInChart = newSelectedDataItemsInChart; + (table.internalProps.layoutMap as PivotLayoutMap).updateDataStateToChartInstance(); + // 清楚chart缓存图片 + clearChartCacheImage(scenegraph); + table.scenegraph.updateNextFrame(); } - - (table.internalProps.layoutMap as PivotLayoutMap).updateDataStateToChartInstance(); - // 清楚chart缓存图片 - clearChartCacheImage(scenegraph); } } diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index fbee0d980..c7daef82f 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -30,7 +30,7 @@ import { updateRow } from './layout/update-row'; import { handleTextStick } from './stick-text'; import { computeRowsHeight } from './layout/compute-row-height'; import { emptyGroup } from './utils/empty-group'; -import { clearChartCacheImage, updateChartSize, updateChartState } from './refresh-node/update-chart'; +import { updateChartSize, updateChartState } from './refresh-node/update-chart'; import { dealFrozen, resetFrozen } from './layout/frozen'; import { createCornerCell } from './style/corner-cell'; diff --git a/packages/vtable/src/state/hover/update-position.ts b/packages/vtable/src/state/hover/update-position.ts index 56fcb6fff..ed7483c56 100644 --- a/packages/vtable/src/state/hover/update-position.ts +++ b/packages/vtable/src/state/hover/update-position.ts @@ -76,8 +76,7 @@ export function updateHoverPosition(state: StateManeger, col: number, row: numbe if (col === -1 || row === -1) { cellPos.col = -1; cellPos.row = -1; - - if (updateScenegraph) { + if (updateScenegraph && (prevHoverCellCol !== col || prevHoverCellRow !== row)) { state.table.scenegraph.updateNextFrame(); } return; diff --git a/packages/vtable/src/tools/util.ts b/packages/vtable/src/tools/util.ts index 68376ab37..70e4ffd23 100644 --- a/packages/vtable/src/tools/util.ts +++ b/packages/vtable/src/tools/util.ts @@ -490,3 +490,45 @@ export function toBoolean(val: unknown): boolean { } return Boolean(val); } + +export function compareArrays(arr1: Array, arr2: Array) { + if (arr1.length !== arr2.length) { + return false; + } + + for (let i = 0; i < arr1.length; i++) { + if (!compareObjects(arr1[i], arr2[i])) { + return false; + } + } + + return true; +} + +export function compareObjects(obj1: any, obj2: any) { + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + + if (keys1.length !== keys2.length) { + return false; + } + + for (const key of keys1) { + if (!obj2.hasOwnProperty(key)) { + return false; + } + + const val1 = obj1[key]; + const val2 = obj2[key]; + + if (typeof val1 === 'object' && typeof val2 === 'object') { + if (!compareObjects(val1, val2)) { + return false; + } + } else if (val1 !== val2) { + return false; + } + } + + return true; +} From c401cfde780cd0db59754f19b377e7cbfe8a8ddd Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 16 Aug 2023 11:36:17 +0800 Subject: [PATCH 2/3] refactor: compare array equal use vutil's isEqual --- .../scenegraph/refresh-node/update-chart.ts | 3 +- packages/vtable/src/tools/util.ts | 42 ------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts index df3f67016..7ef636fd5 100644 --- a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts +++ b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts @@ -1,3 +1,4 @@ +import { isEqual } from '@visactor/vutils'; import type { PivotChart } from '../../PivotChart'; import { CartesianAxis } from '../../components/axis/axis'; import type { PivotLayoutMap } from '../../layout/pivot-layout'; @@ -146,7 +147,7 @@ export function updateChartState(scenegraph: Scenegraph, datum: any) { newSelectedDataItemsInChart.push(selectedState); } //避免无效的更新 - if (!compareArrays((table as PivotChart)._selectedDataItemsInChart, newSelectedDataItemsInChart)) { + if (!isEqual((table as PivotChart)._selectedDataItemsInChart, newSelectedDataItemsInChart)) { (table as PivotChart)._selectedDataItemsInChart = newSelectedDataItemsInChart; (table.internalProps.layoutMap as PivotLayoutMap).updateDataStateToChartInstance(); // 清楚chart缓存图片 diff --git a/packages/vtable/src/tools/util.ts b/packages/vtable/src/tools/util.ts index 70e4ffd23..68376ab37 100644 --- a/packages/vtable/src/tools/util.ts +++ b/packages/vtable/src/tools/util.ts @@ -490,45 +490,3 @@ export function toBoolean(val: unknown): boolean { } return Boolean(val); } - -export function compareArrays(arr1: Array, arr2: Array) { - if (arr1.length !== arr2.length) { - return false; - } - - for (let i = 0; i < arr1.length; i++) { - if (!compareObjects(arr1[i], arr2[i])) { - return false; - } - } - - return true; -} - -export function compareObjects(obj1: any, obj2: any) { - const keys1 = Object.keys(obj1); - const keys2 = Object.keys(obj2); - - if (keys1.length !== keys2.length) { - return false; - } - - for (const key of keys1) { - if (!obj2.hasOwnProperty(key)) { - return false; - } - - const val1 = obj1[key]; - const val2 = obj2[key]; - - if (typeof val1 === 'object' && typeof val2 === 'object') { - if (!compareObjects(val1, val2)) { - return false; - } - } else if (val1 !== val2) { - return false; - } - } - - return true; -} From 330d21e7703d18b88cc3eb2c1a77516baece5219 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 16 Aug 2023 11:37:35 +0800 Subject: [PATCH 3/3] refactor: compare array equal use vutil's isEqual --- packages/vtable/src/scenegraph/refresh-node/update-chart.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts index 7ef636fd5..de522ce64 100644 --- a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts +++ b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts @@ -2,7 +2,6 @@ import { isEqual } from '@visactor/vutils'; import type { PivotChart } from '../../PivotChart'; import { CartesianAxis } from '../../components/axis/axis'; import type { PivotLayoutMap } from '../../layout/pivot-layout'; -import { compareArrays } from '../../tools/util'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { Chart } from '../graphic/chart'; import type { Group } from '../graphic/group';