From f61ed321e8e78c433298d6eab5afd652a6e5a254 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 16 Oct 2024 21:06:18 +0800 Subject: [PATCH 01/14] feat: add InvertHighlightPlugin --- packages/vtable/examples/interactive/mask.ts | 99 ++++++++++++++++ packages/vtable/examples/menu.ts | 4 + packages/vtable/src/index.ts | 2 + .../vtable/src/plugins/invert-highlight.ts | 107 ++++++++++++++++++ .../vtable/src/scenegraph/graphic/group.ts | 4 + .../scenegraph/group-creater/cell-helper.ts | 6 +- packages/vtable/src/tools/cell-range.ts | 18 +++ 7 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 packages/vtable/examples/interactive/mask.ts create mode 100644 packages/vtable/src/plugins/invert-highlight.ts create mode 100644 packages/vtable/src/tools/cell-range.ts diff --git a/packages/vtable/examples/interactive/mask.ts b/packages/vtable/examples/interactive/mask.ts new file mode 100644 index 000000000..388e176cd --- /dev/null +++ b/packages/vtable/examples/interactive/mask.ts @@ -0,0 +1,99 @@ +import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; +const CONTAINER_ID = 'vTable'; +const generatePersons = count => { + return Array.from(new Array(count)).map((_, i) => ({ + id: i + 1, + email1: `${i + 1}@xxx.com`, + name: `小明${i + 1}`, + lastName: '王', + date1: '2022年9月1日', + tel: '000-0000-0000', + sex: i % 2 === 0 ? 'boy' : 'girl', + work: i % 2 === 0 ? 'back-end engineer' + (i + 1) : 'front-end engineer' + (i + 1), + city: 'beijing', + image: + '' + })); +}; + +export function createTable() { + const records = generatePersons(5); + const columns: VTable.ColumnsDefine = [ + { + field: 'image', + title: '行号', + width: 80, + cellType: 'image', + keepAspectRatio: true + }, + { + field: 'id', + title: 'ID', + width: 'auto', + minWidth: 50, + sort: true + }, + { + field: 'email1', + title: 'email', + width: 200, + sort: true, + style: { + underline: true, + underlineDash: [2, 0], + underlineOffset: 3 + } + }, + { + title: 'full name', + columns: [ + { + field: 'name', + title: 'First Name', + width: 200 + }, + { + field: 'name', + title: 'Last Name', + width: 200 + } + ] + }, + { + field: 'date1', + title: 'birthday', + width: 200 + }, + { + field: 'sex', + title: 'sex', + width: 100 + } + ]; + const option: VTable.ListTableConstructorOptions = { + container: document.getElementById(CONTAINER_ID), + records, + columns, + theme: VTable.themes.DARK, + heightMode: 'adaptive' + }; + const tableInstance = new VTable.ListTable(option); + window.tableInstance = tableInstance; + + bindDebugTool(tableInstance.scenegraph.stage, { + customGrapicKeys: ['col', 'row'] + }); + + const highlightPlugin = new VTable.InvertHighlightPlugin(tableInstance); + highlightPlugin.setInvertHighlightRange({ + start: { + col: 0, + row: 6 + }, + end: { + col: 6, + row: 6 + } + }); +} diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index 40f7d7af6..b506cc758 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -633,6 +633,10 @@ export const menus = [ { path: 'interactive', name: 'pre-sort' + }, + { + path: 'interactive', + name: 'mask' } ] }, diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index 0ce1ec896..0c79f2979 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -129,3 +129,5 @@ export * from './scenegraph/group-creater/cell-type'; export { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; export { PIVOT_CHART_EVENT_TYPE, PIVOT_TABLE_EVENT_TYPE } from './ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; + +export { InvertHighlightPlugin } from './plugins/invert-highlight'; diff --git a/packages/vtable/src/plugins/invert-highlight.ts b/packages/vtable/src/plugins/invert-highlight.ts new file mode 100644 index 000000000..3106d911b --- /dev/null +++ b/packages/vtable/src/plugins/invert-highlight.ts @@ -0,0 +1,107 @@ +import type { Rect } from '@src/vrender'; +import { createRect } from '@src/vrender'; +import type { Group } from '../scenegraph/graphic/group'; +import { isSameRange } from '../tools/cell-range'; +import type { CellRange } from '../ts-types'; +import type { BaseTableAPI } from '../ts-types/base-table'; +import { cellInRange } from '../tools/helper'; +import { isValid } from '@visactor/vutils'; + +export interface InvertHighlightPluginOptions { + fill?: string; + opacity?: number; +} + +export class InvertHighlightPlugin { + table: BaseTableAPI; + range?: CellRange; + _fill: string; + _opacity: number; + + constructor(table: BaseTableAPI, options?: InvertHighlightPluginOptions) { + this.table = table; + + this._fill = options?.fill ?? '#000'; + this._opacity = options?.opacity ?? 0.5; + } + + setInvertHighlightRange(range?: CellRange) { + if (isSameRange(this.range, range)) { + return; + } + + this.range = range; + if (!range) { + // reset highlight + this.deleteAllCellGroupShadow(); + } else { + // update highlight + this.updateCellGroupShadow(); + } + + this.table.scenegraph.updateNextFrame(); + } + + deleteAllCellGroupShadow() { + if (!this.table.isPivotTable()) { + this.updateCellGroupShadowInContainer(this.table.scenegraph.rowHeaderGroup); + this.updateCellGroupShadowInContainer(this.table.scenegraph.leftBottomCornerGroup); + } + this.updateCellGroupShadowInContainer(this.table.scenegraph.bodyGroup); + this.updateCellGroupShadowInContainer(this.table.scenegraph.rightFrozenGroup); + this.updateCellGroupShadowInContainer(this.table.scenegraph.bottomFrozenGroup); + this.updateCellGroupShadowInContainer(this.table.scenegraph.rightBottomCornerGroup); + } + + updateCellGroupShadow() { + if (!this.table.isPivotTable()) { + this.updateCellGroupShadowInContainer(this.table.scenegraph.rowHeaderGroup, this.range); + this.updateCellGroupShadowInContainer(this.table.scenegraph.leftBottomCornerGroup, this.range); + } + this.updateCellGroupShadowInContainer(this.table.scenegraph.bodyGroup, this.range); + this.updateCellGroupShadowInContainer(this.table.scenegraph.rightFrozenGroup, this.range); + this.updateCellGroupShadowInContainer(this.table.scenegraph.bottomFrozenGroup), this.range; + this.updateCellGroupShadowInContainer(this.table.scenegraph.rightBottomCornerGroup, this.range); + } + updateCellGroupShadowInContainer(container: Group, range?: CellRange) { + container.forEachChildrenSkipChild((column: Group) => { + if (column.role === 'column') { + column.forEachChildrenSkipChild((cell: Group) => { + if (cell.role !== 'cell') { + return; + } + cell.attachShadow(cell.shadowRoot); + const shadowGroup = cell.shadowRoot; + if (range && !shadowGroup.firstChild && !cellInRange(range, cell.col, cell.row)) { + const shadowRect = createRect({ + x: 0, + y: 0, + width: cell.attribute.width, + height: cell.attribute.height, + fill: this._fill, + opacity: this._opacity + }); + shadowRect.name = 'shadow-rect'; + shadowGroup.appendChild(shadowRect); + } else { + shadowGroup.removeAllChild(); + } + }); + } + }); + } +} + +export function onBeforeAttributeUpdateForInvertHighlight(val: Record, attribute: any) { + // @ts-ignore + const graphic = this as any; + if (graphic.shadowRoot && graphic.shadowRoot.childrenCount && (isValid(val.width) || isValid(val.height))) { + const shadowRect = (graphic.shadowRoot as Group).findChildrenByName('shadow-rect')[0] as Rect; + if (shadowRect) { + shadowRect.setAttributes({ + width: val.width ?? shadowRect.attribute.width, + height: val.height ?? shadowRect.attribute.height + }); + } + } +} diff --git a/packages/vtable/src/scenegraph/graphic/group.ts b/packages/vtable/src/scenegraph/graphic/group.ts index 6b75bb433..fd436b5e5 100644 --- a/packages/vtable/src/scenegraph/graphic/group.ts +++ b/packages/vtable/src/scenegraph/graphic/group.ts @@ -307,6 +307,10 @@ export class Group extends VRenderGroup { // 更新bounds之后需要设置父节点,否则tag丢失 this.parent && this.parent.addChildUpdateBoundTag(); this.clearUpdateBoundTag(); + if (this.shadowRoot) { + // this.shadowRoot.clearUpdateBoundTag(); + this.shadowRoot.tryUpdateAABBBounds(); + } return this._AABBBounds; } else if ( this.role === 'body' || diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 36e20624a..a55f53b06 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -1,4 +1,4 @@ -import type { Cursor, IGraphic, IThemeSpec, Group as VGroup } from '@src/vrender'; +import type { Cursor, IGraphic, IThemeSpec, Rect, Group as VGroup } from '@src/vrender'; import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; import { regUrl } from '../../tools/global'; import type { @@ -33,9 +33,10 @@ import type { CreateCheckboxCellGroup } from './cell-type/checkbox-cell'; import { getHierarchyOffset } from '../utils/get-hierarchy-offset'; import { getQuadProps } from '../utils/padding'; import { updateCellContentHeight, updateCellContentWidth } from '../utils/text-icon-layout'; -import { isArray } from '@visactor/vutils'; +import { isArray, isValid } from '@visactor/vutils'; import { breakString } from '../utils/break-string'; import type { CreateRadioCellGroup } from './cell-type/radio-cell'; +import { onBeforeAttributeUpdateForInvertHighlight } from '../../plugins/invert-highlight'; export function createCell( type: ColumnTypeOption, @@ -386,6 +387,7 @@ export function createCell( ); } + cellGroup.onBeforeAttributeUpdate = onBeforeAttributeUpdateForInvertHighlight as any; return cellGroup; } diff --git a/packages/vtable/src/tools/cell-range.ts b/packages/vtable/src/tools/cell-range.ts new file mode 100644 index 000000000..87e137b89 --- /dev/null +++ b/packages/vtable/src/tools/cell-range.ts @@ -0,0 +1,18 @@ +import type { CellRange } from '../ts-types'; + +export function isSameRange(range1: CellRange | undefined | null, range2: CellRange | undefined | null) { + if (!range1 && !range2) { + return true; + } + + if (!range1 || !range2) { + return false; + } + + return ( + range1.start.col === range2.start.col && + range1.start.row === range2.start.row && + range1.end.col === range2.end.col && + range1.end.row === range2.end.row + ); +} From 11769e5ac4206e10564e08ae769c36ac66bb26cf Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 17 Oct 2024 14:23:42 +0800 Subject: [PATCH 02/14] fix: fix highlight logic in InvertHighlightPlugin --- packages/vtable/examples/interactive/mask.ts | 41 ++++++++++++++----- .../vtable/src/plugins/invert-highlight.ts | 11 +++-- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/vtable/examples/interactive/mask.ts b/packages/vtable/examples/interactive/mask.ts index 388e176cd..aa7137939 100644 --- a/packages/vtable/examples/interactive/mask.ts +++ b/packages/vtable/examples/interactive/mask.ts @@ -18,7 +18,7 @@ const generatePersons = count => { }; export function createTable() { - const records = generatePersons(5); + const records = generatePersons(20); const columns: VTable.ColumnsDefine = [ { field: 'image', @@ -76,7 +76,10 @@ export function createTable() { records, columns, theme: VTable.themes.DARK, - heightMode: 'adaptive' + // heightMode: 'adaptive', + select: { + disableSelect: true + } }; const tableInstance = new VTable.ListTable(option); window.tableInstance = tableInstance; @@ -86,14 +89,32 @@ export function createTable() { }); const highlightPlugin = new VTable.InvertHighlightPlugin(tableInstance); - highlightPlugin.setInvertHighlightRange({ - start: { - col: 0, - row: 6 - }, - end: { - col: 6, - row: 6 + // highlightPlugin.setInvertHighlightRange({ + // start: { + // col: 0, + // row: 6 + // }, + // end: { + // col: 6, + // row: 6 + // } + // }); + + tableInstance.on('click_cell', event => { + const { col, row } = event; + if (tableInstance.isHeader(col, row)) { + highlightPlugin.setInvertHighlightRange(undefined); + } else { + highlightPlugin.setInvertHighlightRange({ + start: { + col: 0, + row + }, + end: { + col: tableInstance.colCount - 1, + row + } + }); } }); } diff --git a/packages/vtable/src/plugins/invert-highlight.ts b/packages/vtable/src/plugins/invert-highlight.ts index 3106d911b..2dcabf4b2 100644 --- a/packages/vtable/src/plugins/invert-highlight.ts +++ b/packages/vtable/src/plugins/invert-highlight.ts @@ -72,7 +72,14 @@ export class InvertHighlightPlugin { } cell.attachShadow(cell.shadowRoot); const shadowGroup = cell.shadowRoot; - if (range && !shadowGroup.firstChild && !cellInRange(range, cell.col, cell.row)) { + if (!range) { + // no highlight + shadowGroup.removeAllChild(); + } else if (cellInRange(range, cell.col, cell.row)) { + // inside highlight + shadowGroup.removeAllChild(); + } else if (!shadowGroup.firstChild) { + // outside highlight const shadowRect = createRect({ x: 0, y: 0, @@ -83,8 +90,6 @@ export class InvertHighlightPlugin { }); shadowRect.name = 'shadow-rect'; shadowGroup.appendChild(shadowRect); - } else { - shadowGroup.removeAllChild(); } }); } From 280296099777b3c8e667bf6343fc3cb383abb052 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 17 Oct 2024 16:37:12 +0800 Subject: [PATCH 03/14] feat: add CarouselAnimationPlugin --- packages/vtable/examples/interactive/mask.ts | 12 ++ packages/vtable/src/index.ts | 1 + .../vtable/src/plugins/carousel-animation.ts | 117 ++++++++++++++++++ packages/vtable/src/ts-types/base-table.ts | 6 +- 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 packages/vtable/src/plugins/carousel-animation.ts diff --git a/packages/vtable/examples/interactive/mask.ts b/packages/vtable/examples/interactive/mask.ts index aa7137939..49eba6c4c 100644 --- a/packages/vtable/examples/interactive/mask.ts +++ b/packages/vtable/examples/interactive/mask.ts @@ -117,4 +117,16 @@ export function createTable() { }); } }); + + const ca = new VTable.CarouselAnimationPlugin(tableInstance, { + rowCount: 2, + replaceScrollAction: true + }); + + // ca.play(); + + // setInterval(() => { + // row += 2; + // tableInstance.scrollToRow(row, { duration: 500 }); + // }, 2000); } diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index 0c79f2979..e454ac211 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -131,3 +131,4 @@ export { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; export { PIVOT_CHART_EVENT_TYPE, PIVOT_TABLE_EVENT_TYPE } from './ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; export { InvertHighlightPlugin } from './plugins/invert-highlight'; +export { CarouselAnimationPlugin } from './plugins/carousel-animation'; diff --git a/packages/vtable/src/plugins/carousel-animation.ts b/packages/vtable/src/plugins/carousel-animation.ts new file mode 100644 index 000000000..ee48b1a64 --- /dev/null +++ b/packages/vtable/src/plugins/carousel-animation.ts @@ -0,0 +1,117 @@ +import type { EasingType } from '@src/vrender'; +import type { BaseTableAPI } from '../ts-types/base-table'; + +export interface ICarouselAnimationPluginOptions { + rowCount?: number; + colCount?: number; + animationDuration?: number; + animationDelay?: number; + animationEasing?: EasingType; + replaceScrollAction?: boolean; +} + +export class CarouselAnimationPlugin { + table: BaseTableAPI; + + rowCount: number; + colCount: number; + animationDuration: number; + animationDelay: number; + animationEasing: EasingType; + replaceScrollAction: boolean; + + playing: boolean; + row: number; + col: number; + constructor(table: BaseTableAPI, options?: ICarouselAnimationPluginOptions) { + this.table = table; + + this.rowCount = options?.rowCount ?? undefined; + this.colCount = options?.colCount ?? undefined; + this.animationDuration = options?.animationDuration ?? 500; + this.animationDelay = options?.animationDelay ?? 1000; + this.animationEasing = options?.animationEasing ?? 'linear'; + this.replaceScrollAction = options?.replaceScrollAction ?? false; + + this.playing = false; + this.row = table.frozenRowCount; + this.col = table.frozenColCount; + + this.init(); + } + + init() { + if (this.replaceScrollAction) { + this.table.disableScroll(); + + this.table.scenegraph.stage.addEventListener('wheel', this.onScrollEnd.bind(this)); + } + } + + onScrollEnd(e: Event) { + if (this.rowCount) { + if ((e as any).deltaY > 0) { + this.row += this.rowCount; + this.row = Math.min(this.row, this.table.rowCount - this.table.frozenRowCount); + } else if ((e as any).deltaY < 0) { + this.row -= this.rowCount; + this.row = Math.max(this.row, this.table.frozenRowCount); + } + this.table.scrollToRow(this.row, { duration: this.animationDuration, easing: this.animationEasing }); + } else if (this.colCount) { + if ((e as any).deltaX > 0) { + this.col += this.colCount; + this.col = Math.min(this.col, this.table.colCount - this.table.frozenColCount); + } else if ((e as any).deltaX < 0) { + this.col -= this.colCount; + this.col = Math.max(this.col, this.table.frozenColCount); + } + this.table.scrollToCol(this.col, { duration: this.animationDuration, easing: this.animationEasing }); + } + } + + play() { + this.playing = true; + + if (this.rowCount) { + this.updateRow(); + } else if (this.colCount) { + this.updateCol(); + } + } + + pause() { + this.playing = false; + } + + updateRow() { + if (!this.playing) { + return; + } + if (this.table.scenegraph.proxy.screenTopRow !== this.row) { + this.row = this.table.frozenRowCount; + } else { + this.row += this.rowCount; + } + this.table.scrollToRow(this.row, { duration: this.animationDuration, easing: this.animationEasing }); + setTimeout(() => { + this.updateRow(); + }, this.animationDuration + this.animationDelay); + } + + updateCol() { + if (!this.playing) { + return; + } + if (this.table.scenegraph.proxy.screenLeftCol !== this.col) { + this.col = this.table.frozenColCount; + } else { + this.col += this.colCount; + } + + this.table.scrollToCol(this.col, { duration: this.animationDuration, easing: this.animationEasing }); + setTimeout(() => { + this.updateCol(); + }, this.animationDuration + 50); + } +} diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 73a1f9198..352b262ea 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -100,7 +100,7 @@ import type { IEmptyTip } from './component/empty-tip'; import type { EmptyTip } from '../components/empty-tip/empty-tip'; import type { CustomCellStylePlugin } from '../plugins/custom-cell-style'; import type { EditManeger } from '../edit/edit-manager'; -import type { TableAnimationManager } from '../core/animation'; +import type { ITableAnimationOption, TableAnimationManager } from '../core/animation'; export interface IBaseTableProtected { element: HTMLElement; @@ -849,7 +849,9 @@ export interface BaseTableAPI { * 滚动到具体某个单元格位置 * @param cellAddr 要滚动到的单元格位置 */ - scrollToCell: (cellAddr: { col?: number; row?: number }) => void; + scrollToCell: (cellAddr: { col?: number; row?: number }, animationOption?: ITableAnimationOption | boolean) => void; + scrollToRow: (row: number, animationOption?: ITableAnimationOption | boolean) => void; + scrollToCol: (col: number, animationOption?: ITableAnimationOption | boolean) => void; registerCustomCellStyle: (customStyleId: string, customStyle: ColumnStyleOption | undefined | null) => void; arrangeCustomCellStyle: (cellPos: { col?: number; row?: number; range?: CellRange }, customStyleId: string) => void; From 949597de89a346f84793dd58209ad72bb73dbcb8 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 17 Oct 2024 17:02:32 +0800 Subject: [PATCH 04/14] chore: update rush change --- .../@visactor/vtable/feat-fs-bs_2024-10-17-09-01.json | 10 ++++++++++ .../@visactor/vtable/feat-fs-bs_2024-10-17-09-02.json | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-01.json create mode 100644 common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-02.json diff --git a/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-01.json b/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-01.json new file mode 100644 index 000000000..30ab08dc0 --- /dev/null +++ b/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-01.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add InvertHighlightPlugin ", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-02.json b/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-02.json new file mode 100644 index 000000000..71ced78d6 --- /dev/null +++ b/common/changes/@visactor/vtable/feat-fs-bs_2024-10-17-09-02.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: add CarouselAnimationPlugin", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file From ce685f57e4d358531e33af0901bc240bb476ddf2 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 18 Oct 2024 17:19:43 +0800 Subject: [PATCH 05/14] fix: fix header adaptive height computation --- packages/vtable/src/scenegraph/layout/compute-row-height.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index 2924b51aa..b1caf3447 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -91,7 +91,9 @@ export function computeRowsHeight( const height = computeRowHeight(row, startCol, endCol, table); newHeights[row] = Math.round(height); //表头部分需要马上设置到缓存中 因为adaptive不会调整表头的高度 另外后面adaptive处理过程中有取值 table.getRowsHeight(0, table.columnHeaderLevelCount - 1); - table._setRowHeight(row, height); + if (table.heightAdaptiveMode === 'only-body') { + table._setRowHeight(row, height); + } } } From eccf16cc72d58ccb706b1d26da1eccd7e44b56e8 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 30 Oct 2024 11:22:26 +0800 Subject: [PATCH 06/14] fix: fix animation config in TableAnimatinManager --- packages/vtable/src/core/animation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vtable/src/core/animation.ts b/packages/vtable/src/core/animation.ts index 80750a045..61096aa93 100644 --- a/packages/vtable/src/core/animation.ts +++ b/packages/vtable/src/core/animation.ts @@ -1,5 +1,5 @@ import type { EasingType, IRect } from '@src/vrender'; -import { DefaultTimeline, DefaultTicker, Animate, ACustomAnimate, createRect } from '@src/vrender'; +import { DefaultTimeline, DefaultTicker, Animate, ACustomAnimate, createRect, Generator } from '@src/vrender'; import type { BaseTableAPI } from '../ts-types/base-table'; import { isBoolean, isNumber } from '@visactor/vutils'; @@ -48,13 +48,13 @@ export class TableAnimationManager { const duration = !isBoolean(animationOption) ? animationOption?.duration ?? 3000 : animationOption ? 3000 : 0; const easing = !isBoolean(animationOption) ? animationOption?.easing ?? 'linear' : animationOption ? 'linear' : ''; - const animation = new Animate().bind(this.tempGraphic).play( + const animation = new Animate(Generator.GenAutoIncrementId(), this.timeline).bind(this.tempGraphic).play( new Animateaaa(from, to, duration, easing, { graphic: this.tempGraphic, table: this.table }) ); - this.timeline.addAnimate(animation); + // this.timeline.addAnimate(animation); this.ticker.start(); } From 0cefba0cc7283fc02856ab284d71d662cee2a7cc Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 31 Oct 2024 21:45:48 +0800 Subject: [PATCH 07/14] feat: add autoHeightInAdaptiveMode config --- packages/vtable/src/scenegraph/layout/compute-row-height.ts | 6 ++++-- packages/vtable/src/ts-types/base-table.ts | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index b1caf3447..60127129e 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -57,7 +57,9 @@ export function computeRowsHeight( const isDefaultHeaderHasAuto = table.defaultHeaderRowHeight === 'auto' || (isArray(table.defaultHeaderRowHeight) && table.defaultHeaderRowHeight.some(item => item === 'auto')); - const isAllRowsAuto = table.heightMode === 'autoHeight' || table.heightMode === 'adaptive'; + const isAllRowsAuto = + table.heightMode === 'autoHeight' || + (table.heightMode === 'adaptive' && table.options.autoHeightInAdaptiveMode !== false); if (isAllRowsAuto || isDefaultHeaderHasAuto) { rowStart = rowStart ?? 0; @@ -91,7 +93,7 @@ export function computeRowsHeight( const height = computeRowHeight(row, startCol, endCol, table); newHeights[row] = Math.round(height); //表头部分需要马上设置到缓存中 因为adaptive不会调整表头的高度 另外后面adaptive处理过程中有取值 table.getRowsHeight(0, table.columnHeaderLevelCount - 1); - if (table.heightAdaptiveMode === 'only-body') { + if (table.heightAdaptiveMode === 'only-body' || !update) { table._setRowHeight(row, height); } } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index cb9253824..0e8481036 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -419,6 +419,8 @@ export interface BaseTableConstructorOptions { /** adaptive 模式下高度的适应策略 **/ heightAdaptiveMode?: HeightAdaptiveModeDef; + autoHeightInAdaptiveMode?: boolean; + // /** 行高是否根据内容来计算 */ // autoRowHeight?: boolean; /** 设备的像素比 不配的话默认获取window.devicePixelRatio */ From f1cc43916f67f437002cceb78483d057ed034281 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 5 Nov 2024 11:05:07 +0800 Subject: [PATCH 08/14] feat: add limitContentHeight config --- .../scenegraph/group-creater/cell-helper.ts | 6 +++-- .../scenegraph/layout/compute-row-height.ts | 5 +++- .../src/scenegraph/layout/update-height.ts | 6 +++-- .../src/scenegraph/utils/text-icon-layout.ts | 27 ++++++++++++++----- packages/vtable/src/ts-types/base-table.ts | 3 +++ 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index a55f53b06..d447d83e1 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -904,7 +904,8 @@ export function dealWithMergeCellSize( table.isAutoRowHeight(row), padding, textAlign, - textBaseline + textBaseline, + table // 'middle' ); } @@ -954,7 +955,8 @@ export function dealWithMergeCellSizeForShadow( table.isAutoRowHeight(row), padding, textAlign, - textBaseline + textBaseline, + table // 'middle' ); } diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index 60127129e..c12b392c8 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -297,7 +297,10 @@ export function computeRowsHeight( if (update) { for (let row = rowStart; row <= rowEnd; row++) { const newRowHeight = newHeights[row] ?? table.getRowHeight(row); - if (newRowHeight !== (oldRowHeights[row] ?? table.getRowHeight(row))) { + // if (newRowHeight !== (oldRowHeights[row] ?? table.getRowHeight(row))) { + // table._setRowHeight(row, newRowHeight); + // } + if (isValid(newRowHeight)) { table._setRowHeight(row, newRowHeight); } } diff --git a/packages/vtable/src/scenegraph/layout/update-height.ts b/packages/vtable/src/scenegraph/layout/update-height.ts index 3de0e22c3..148441516 100644 --- a/packages/vtable/src/scenegraph/layout/update-height.ts +++ b/packages/vtable/src/scenegraph/layout/update-height.ts @@ -361,7 +361,8 @@ function updateMergeCellContentHeight( autoRowHeight, getQuadProps(style.padding as number), style.textAlign, - style.textBaseline + style.textBaseline, + table ); } @@ -402,7 +403,8 @@ function updateMergeCellContentHeight( autoRowHeight, getQuadProps(style.padding as number), style.textAlign, - style.textBaseline + style.textBaseline, + table ); } } diff --git a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts index e89c3680b..652929b71 100644 --- a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts +++ b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts @@ -103,12 +103,19 @@ export function createCellContent( wordBreak: 'break-word', // widthLimit: autoColWidth ? -1 : colWidth - (padding[1] + padding[3]), heightLimit: - autoRowHeight && !table.options.customConfig?.multilinesForXTable + table.options.customConfig?.limitContentHeight === false + ? -1 + : autoRowHeight && !table.options.customConfig?.multilinesForXTable ? -1 : cellHeight - Math.floor(padding[0] + padding[2]), pickable: false, dx: (textAlign === 'left' ? hierarchyOffset : 0) + _contentOffset, - whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal' + whiteSpace: + table.options.customConfig?.limitContentHeight === false + ? 'normal' + : text.length === 1 && !autoWrapText + ? 'no-wrap' + : 'normal' }; const wrapText = new Text(cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute); wrapText.name = 'text'; @@ -241,14 +248,21 @@ export function createCellContent( textBaseline: 'top', // widthLimit: autoColWidth ? -1 : colWidth - (padding[1] + padding[3]), heightLimit: - autoRowHeight && !table.options.customConfig?.multilinesForXTable + table.options.customConfig?.limitContentHeight === false + ? -1 + : autoRowHeight && !table.options.customConfig?.multilinesForXTable ? -1 : cellHeight - Math.floor(padding[0] + padding[2]), pickable: false, autoWrapText, lineClamp, wordBreak: 'break-word', - whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal', + whiteSpace: + table.options.customConfig?.limitContentHeight === false + ? 'normal' + : text.length === 1 && !autoWrapText + ? 'no-wrap' + : 'normal', dx: (textAlign === 'left' ? (!contentLeftIcons.length ? hierarchyOffset : 0) : 0) + _contentOffset }; const wrapText = new Text(cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute); @@ -702,7 +716,8 @@ export function updateCellContentHeight( autoRowHeight: boolean, padding: [number, number, number, number], textAlign: CanvasTextAlign, - textBaseline: CanvasTextBaseline + textBaseline: CanvasTextBaseline, + table: BaseTableAPI ) { const newHeight = distHeight - Math.floor(padding[0] + padding[2]); @@ -710,7 +725,7 @@ export function updateCellContentHeight( if (textMark instanceof Text && !autoRowHeight) { textMark.setAttributes({ - heightLimit: newHeight + heightLimit: table.options.customConfig?.limitContentHeight === false ? -1 : newHeight } as any); } else if (textMark instanceof RichText && !autoRowHeight) { textMark.setAttributes({ diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 0e8481036..00a0e3480 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -506,6 +506,9 @@ export interface BaseTableConstructorOptions { // 行列移动不更新表格 notUpdateInColumnRowMove?: boolean; + + // 表格是否限制内容高度 + limitContentHeight?: boolean; }; // 部分特殊配置,兼容xTable等作用 animationAppear?: boolean | IAnimationAppear; From baa038a697b793031afa4021b862b7c0cd52a434 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 6 Nov 2024 17:32:27 +0800 Subject: [PATCH 09/14] feat: add HeaderHighlightPlugin --- .../examples/interactive/highlight-color.ts | 82 +++++++++ packages/vtable/examples/menu.ts | 4 + packages/vtable/src/index.ts | 5 +- .../vtable/src/plugins/custom-cell-style.ts | 59 +++++-- .../vtable/src/plugins/header-highlight.ts | 158 ++++++++++++++++++ 5 files changed, 288 insertions(+), 20 deletions(-) create mode 100644 packages/vtable/examples/interactive/highlight-color.ts create mode 100644 packages/vtable/src/plugins/header-highlight.ts diff --git a/packages/vtable/examples/interactive/highlight-color.ts b/packages/vtable/examples/interactive/highlight-color.ts new file mode 100644 index 000000000..421cb1059 --- /dev/null +++ b/packages/vtable/examples/interactive/highlight-color.ts @@ -0,0 +1,82 @@ +import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; +const CONTAINER_ID = 'vTable'; +const generatePersons = count => { + return Array.from(new Array(count)).map((_, i) => ({ + id: i + 1, + email1: `${i + 1}@xxx.com`, + name: `小明${i + 1}`, + lastName: '王', + date1: '2022年9月1日', + tel: '000-0000-0000', + sex: i % 2 === 0 ? 'boy' : 'girl', + work: i % 2 === 0 ? 'back-end engineer' + (i + 1) : 'front-end engineer' + (i + 1), + city: 'beijing', + image: + '' + })); +}; + +export function createTable() { + const records = generatePersons(20); + const columns: VTable.ColumnsDefine = [ + { + field: 'id', + title: 'ID', + width: 'auto', + minWidth: 50, + sort: true + }, + { + field: 'email1', + title: 'email', + width: 200, + sort: true, + style: { + underline: true, + underlineDash: [2, 0], + underlineOffset: 3 + } + }, + { + title: 'full name', + columns: [ + { + field: 'name', + title: 'First Name', + width: 200 + }, + { + field: 'name', + title: 'Last Name', + width: 200 + } + ] + }, + { + field: 'date1', + title: 'birthday', + width: 200 + }, + { + field: 'sex', + title: 'sex', + width: 100 + } + ]; + const option: VTable.ListTableConstructorOptions = { + container: document.getElementById(CONTAINER_ID), + records, + columns, + rowSeriesNumber: {} + }; + const tableInstance = new VTable.ListTable(option); + window.tableInstance = tableInstance; + + bindDebugTool(tableInstance.scenegraph.stage, { + customGrapicKeys: ['col', 'row'] + }); + + const highlightPlugin = new VTable.HeaderHighlightPlugin(tableInstance); + window.highlightPlugin = highlightPlugin; +} diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index f1196ed59..bb1769086 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -645,6 +645,10 @@ export const menus = [ { path: 'interactive', name: 'mask' + }, + { + path: 'interactive', + name: 'highlight-color' } ] }, diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index e454ac211..982870f04 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -130,5 +130,6 @@ export * from './scenegraph/group-creater/cell-type'; export { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; export { PIVOT_CHART_EVENT_TYPE, PIVOT_TABLE_EVENT_TYPE } from './ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; -export { InvertHighlightPlugin } from './plugins/invert-highlight'; -export { CarouselAnimationPlugin } from './plugins/carousel-animation'; +export * from './plugins/invert-highlight'; +export * from './plugins/carousel-animation'; +export * from './plugins/header-highlight'; diff --git a/packages/vtable/src/plugins/custom-cell-style.ts b/packages/vtable/src/plugins/custom-cell-style.ts index 210204dc9..5174295c8 100644 --- a/packages/vtable/src/plugins/custom-cell-style.ts +++ b/packages/vtable/src/plugins/custom-cell-style.ts @@ -34,20 +34,28 @@ export class CustomCellStylePlugin { getCustomCellStyleId(col: number, row: number) { let customStyleId; - this.customCellStyleArrangement.forEach(style => { - if (style.cellPosition.range) { - if ( - style.cellPosition.range.start.col <= col && - style.cellPosition.range.end.col >= col && - style.cellPosition.range.start.row <= row && - style.cellPosition.range.end.row >= row - ) { - customStyleId = style.customStyleId; - } - } else if (style.cellPosition.col === col && style.cellPosition.row === row) { - customStyleId = style.customStyleId; + + const range = this.table.getCellRange(col, row); + for (let c = range.start.col; c <= range.end.col; c++) { + for (let r = range.start.row; r <= range.end.row; r++) { + // eslint-disable-next-line no-loop-func + this.customCellStyleArrangement.forEach(style => { + if (style.cellPosition.range) { + if ( + style.cellPosition.range.start.col <= c && + style.cellPosition.range.end.col >= c && + style.cellPosition.range.start.row <= r && + style.cellPosition.range.end.row >= r + ) { + customStyleId = style.customStyleId; + } + } else if (style.cellPosition.col === c && style.cellPosition.row === r) { + customStyleId = style.customStyleId; + } + }); } - }); + } + return customStyleId; } @@ -106,7 +114,11 @@ export class CustomCellStylePlugin { return style.cellPosition.col === cellPos.col && style.cellPosition.row === cellPos.row; }); - if (index === -1) { + if (index === -1 && !customStyleId) { + // do nothing + return; + } else if (index === -1 && customStyleId) { + // add new style this.customCellStyleArrangement.push({ cellPosition: { col: cellPos.col, @@ -116,16 +128,27 @@ export class CustomCellStylePlugin { customStyleId: customStyleId }); } else if (this.customCellStyleArrangement[index].customStyleId === customStyleId) { + // same style return; - } else { + } else if (customStyleId) { + // update style this.customCellStyleArrangement[index].customStyleId = customStyleId; + } else { + // delete useless style + this.customCellStyleArrangement.splice(index, 1); } // update cell group if (cellPos.range) { for (let col = cellPos.range.start.col; col <= cellPos.range.end.col; col++) { for (let row = cellPos.range.start.row; row <= cellPos.range.end.row; row++) { - this.table.scenegraph.updateCellContent(col, row); + const range = this.table.getCellRange(col, row); + for (let c = range.start.col; c <= range.end.col; c++) { + for (let r = range.start.row; r <= range.end.row; r++) { + this.table.scenegraph.updateCellContent(c, r); + } + } + // this.table.scenegraph.updateCellContent(col, row); } } } else { @@ -154,9 +177,9 @@ export function mergeStyle(cacheStyle: Style, customCellStyle: ColumnStyleOption cacheStyle = cacheStyle.clone(); for (const key in customCellStyle) { - const value = customCellStyle[key]; + const value = (customCellStyle as any)[key]; if (value) { - cacheStyle[`_${key}`] = value; + (cacheStyle as any)[`_${key}`] = value; } } diff --git a/packages/vtable/src/plugins/header-highlight.ts b/packages/vtable/src/plugins/header-highlight.ts new file mode 100644 index 000000000..abc866ffd --- /dev/null +++ b/packages/vtable/src/plugins/header-highlight.ts @@ -0,0 +1,158 @@ +import type { CellRange } from '../ts-types'; +import type { BaseTableAPI } from '../ts-types/base-table'; + +export interface IHeaderHighlightPluginOptions { + rowHighlight?: boolean; + colHighlight?: boolean; + colHighlightBGColor?: string; + colHighlightColor?: string; + rowHighlightBGColor?: string; + rowHighlightColor?: string; +} + +export class HeaderHighlightPlugin { + table: BaseTableAPI; + options: IHeaderHighlightPluginOptions; + colHeaderRange?: CellRange; + rowHeaderRange?: CellRange; + constructor(table: BaseTableAPI, options?: IHeaderHighlightPluginOptions) { + this.table = table; + this.options = options; + + this.registerStyle(); + this.bindEvent(); + } + + registerStyle() { + this.table.registerCustomCellStyle('col-highlight', { + bgColor: this.options?.colHighlightBGColor ?? '#82b2f5', + color: this.options?.colHighlightColor ?? '#FFF' + }); + + this.table.registerCustomCellStyle('row-highlight', { + bgColor: this.options?.rowHighlightBGColor ?? '#82b2f5', + color: this.options?.rowHighlightColor ?? '#FFF' + }); + } + + bindEvent() { + this.table.on('selected_cell', e => { + this.updateHighlight(); + }); + + this.table.on('selected_clear', () => { + this.clearHighlight(); + }); + } + + clearHighlight() { + this.colHeaderRange && this.table.arrangeCustomCellStyle({ range: this.colHeaderRange }, undefined); + this.rowHeaderRange && this.table.arrangeCustomCellStyle({ range: this.rowHeaderRange }, undefined); + + // clear range + this.colHeaderRange = undefined; + this.rowHeaderRange = undefined; + } + + updateHighlight() { + if (this.options?.colHighlight === false && this.options?.rowHighlight === false) { + return; + } + const selectRanges = this.table.getSelectedCellRanges(); + if (selectRanges.length === 0) { + this.clearHighlight(); + return; + } + + const selectRange = selectRanges[0]; + const rowSelectRange = [selectRange.start.row, selectRange.end.row]; + rowSelectRange.sort((a, b) => a - b); // sort + const colSelectRange = [selectRange.start.col, selectRange.end.col]; + colSelectRange.sort((a, b) => a - b); // sort + + let colHeaderRange: CellRange; + let rowHeaderRange: CellRange; + if (this.table.isPivotTable()) { + colHeaderRange = { + start: { + col: colSelectRange[0], + row: 0 + }, + end: { + col: colSelectRange[1], + row: this.table.columnHeaderLevelCount - 1 + } + }; + rowHeaderRange = { + start: { + col: 0, + row: rowSelectRange[0] + }, + end: { + col: this.table.rowHeaderLevelCount - 1, + row: rowSelectRange[1] + } + }; + } else if (this.table.internalProps.transpose) { + rowHeaderRange = { + start: { + col: 0, + row: rowSelectRange[0] + }, + end: { + col: this.table.rowHeaderLevelCount - 1, + row: rowSelectRange[1] + } + }; + } else { + colHeaderRange = { + start: { + col: colSelectRange[0], + row: 0 + }, + end: { + col: colSelectRange[1], + row: this.table.columnHeaderLevelCount - 1 + } + }; + if (this.table.internalProps.rowSeriesNumber) { + rowHeaderRange = { + start: { + col: 0, + row: rowSelectRange[0] + 1 + }, + end: { + col: 0, + row: rowSelectRange[1] + 1 + } + }; + } + } + + if (this.options?.colHighlight !== false && !isSameRange(this.colHeaderRange, colHeaderRange)) { + this.colHeaderRange && this.table.arrangeCustomCellStyle({ range: this.colHeaderRange }, undefined); + colHeaderRange && this.table.arrangeCustomCellStyle({ range: colHeaderRange }, 'col-highlight'); + this.colHeaderRange = colHeaderRange; + } + + if (this.options?.rowHighlight !== false && !isSameRange(this.rowHeaderRange, rowHeaderRange)) { + this.rowHeaderRange && this.table.arrangeCustomCellStyle({ range: this.rowHeaderRange }, undefined); + rowHeaderRange && this.table.arrangeCustomCellStyle({ range: rowHeaderRange }, 'row-highlight'); + this.rowHeaderRange = rowHeaderRange; + } + } +} + +function isSameRange(a: CellRange | undefined, b: CellRange | undefined) { + if (a === undefined && b === undefined) { + return true; + } + + if (a === undefined || b === undefined) { + return false; + } + + return ( + a.start.col === b.start.col && a.start.row === b.start.row && a.end.col === b.end.col && a.end.row === b.end.row + ); +} From 236a8656a9a38c59e964d728b06465368574a878 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 6 Nov 2024 19:29:52 +0800 Subject: [PATCH 10/14] fix: fix row pos in HeaderHighlightPlugin --- packages/vtable/src/plugins/header-highlight.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/plugins/header-highlight.ts b/packages/vtable/src/plugins/header-highlight.ts index abc866ffd..371a7315f 100644 --- a/packages/vtable/src/plugins/header-highlight.ts +++ b/packages/vtable/src/plugins/header-highlight.ts @@ -119,11 +119,11 @@ export class HeaderHighlightPlugin { rowHeaderRange = { start: { col: 0, - row: rowSelectRange[0] + 1 + row: rowSelectRange[0] }, end: { col: 0, - row: rowSelectRange[1] + 1 + row: rowSelectRange[1] } }; } From 0ded7cf4a53d6e3b374ee29c814ad5dd40eb2b8d Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 7 Nov 2024 11:40:15 +0800 Subject: [PATCH 11/14] fix: fix build problem in vue-vtable --- packages/vue-vtable/src/tables/base-table.vue | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/packages/vue-vtable/src/tables/base-table.vue b/packages/vue-vtable/src/tables/base-table.vue index bc5631ce4..ef26edfc1 100644 --- a/packages/vue-vtable/src/tables/base-table.vue +++ b/packages/vue-vtable/src/tables/base-table.vue @@ -1,5 +1,6 @@ From ee6c9c2c421554effa91f8b9f9a7a269ef53a30e Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 12 Nov 2024 11:12:56 +0800 Subject: [PATCH 12/14] feat: change animation logic in CarouselAnimationPlugin --- .../vtable/src/plugins/carousel-animation.ts | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/vtable/src/plugins/carousel-animation.ts b/packages/vtable/src/plugins/carousel-animation.ts index ee48b1a64..2f93e3e2e 100644 --- a/packages/vtable/src/plugins/carousel-animation.ts +++ b/packages/vtable/src/plugins/carousel-animation.ts @@ -88,30 +88,48 @@ export class CarouselAnimationPlugin { if (!this.playing) { return; } + + let animation = true; if (this.table.scenegraph.proxy.screenTopRow !== this.row) { this.row = this.table.frozenRowCount; + animation = false; } else { this.row += this.rowCount; } - this.table.scrollToRow(this.row, { duration: this.animationDuration, easing: this.animationEasing }); - setTimeout(() => { - this.updateRow(); - }, this.animationDuration + this.animationDelay); + this.table.scrollToRow( + this.row, + animation ? { duration: this.animationDuration, easing: this.animationEasing } : undefined + ); + setTimeout( + () => { + this.updateRow(); + }, + animation ? this.animationDuration + this.animationDelay : 0 + ); } updateCol() { if (!this.playing) { return; } + + let animation = true; if (this.table.scenegraph.proxy.screenLeftCol !== this.col) { this.col = this.table.frozenColCount; + animation = false; } else { this.col += this.colCount; } - this.table.scrollToCol(this.col, { duration: this.animationDuration, easing: this.animationEasing }); - setTimeout(() => { - this.updateCol(); - }, this.animationDuration + 50); + this.table.scrollToCol( + this.col, + animation ? { duration: this.animationDuration, easing: this.animationEasing } : undefined + ); + setTimeout( + () => { + this.updateCol(); + }, + animation ? this.animationDuration + this.animationDelay : 0 + ); } } From b34cc3a51f8e78c37df9f3683055c6478fe994fa Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 13 Nov 2024 14:56:12 +0800 Subject: [PATCH 13/14] fix: change scroll to top animation in CarouselAnimationPlugin --- packages/vtable/src/plugins/carousel-animation.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/plugins/carousel-animation.ts b/packages/vtable/src/plugins/carousel-animation.ts index 2f93e3e2e..a2fbb08d7 100644 --- a/packages/vtable/src/plugins/carousel-animation.ts +++ b/packages/vtable/src/plugins/carousel-animation.ts @@ -104,7 +104,8 @@ export class CarouselAnimationPlugin { () => { this.updateRow(); }, - animation ? this.animationDuration + this.animationDelay : 0 + // animation ? this.animationDuration + this.animationDelay : 0 + this.animationDuration + this.animationDelay ); } @@ -129,7 +130,8 @@ export class CarouselAnimationPlugin { () => { this.updateCol(); }, - animation ? this.animationDuration + this.animationDelay : 0 + // animation ? this.animationDuration + this.animationDelay : 0 + this.animationDuration + this.animationDelay ); } } From 62bc90724c5d8942179480e11f6a5b4fc845bd92 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 14 Nov 2024 15:37:37 +0800 Subject: [PATCH 14/14] fix: fix play async task count in CarouselAnimationPlugin --- .../vtable/src/plugins/carousel-animation.ts | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/vtable/src/plugins/carousel-animation.ts b/packages/vtable/src/plugins/carousel-animation.ts index a2fbb08d7..35fff969d 100644 --- a/packages/vtable/src/plugins/carousel-animation.ts +++ b/packages/vtable/src/plugins/carousel-animation.ts @@ -23,6 +23,8 @@ export class CarouselAnimationPlugin { playing: boolean; row: number; col: number; + willUpdateRow: boolean = false; + willUpdateCol: boolean = false; constructor(table: BaseTableAPI, options?: ICarouselAnimationPluginOptions) { this.table = table; @@ -33,10 +35,7 @@ export class CarouselAnimationPlugin { this.animationEasing = options?.animationEasing ?? 'linear'; this.replaceScrollAction = options?.replaceScrollAction ?? false; - this.playing = false; - this.row = table.frozenRowCount; - this.col = table.frozenColCount; - + this.reset(); this.init(); } @@ -48,6 +47,12 @@ export class CarouselAnimationPlugin { } } + reset() { + this.playing = false; + this.row = this.table.frozenRowCount; + this.col = this.table.frozenColCount; + } + onScrollEnd(e: Event) { if (this.rowCount) { if ((e as any).deltaY > 0) { @@ -73,9 +78,9 @@ export class CarouselAnimationPlugin { play() { this.playing = true; - if (this.rowCount) { + if (this.rowCount && !this.willUpdateRow) { this.updateRow(); - } else if (this.colCount) { + } else if (this.colCount && !this.willUpdateCol) { this.updateCol(); } } @@ -100,8 +105,10 @@ export class CarouselAnimationPlugin { this.row, animation ? { duration: this.animationDuration, easing: this.animationEasing } : undefined ); + this.willUpdateRow = true; setTimeout( () => { + this.willUpdateRow = false; this.updateRow(); }, // animation ? this.animationDuration + this.animationDelay : 0 @@ -126,8 +133,11 @@ export class CarouselAnimationPlugin { this.col, animation ? { duration: this.animationDuration, easing: this.animationEasing } : undefined ); + + this.willUpdateCol = true; setTimeout( () => { + this.willUpdateCol = false; this.updateCol(); }, // animation ? this.animationDuration + this.animationDelay : 0