diff --git a/common/changes/@visactor/vtable/feat-package-size_2024-07-01-07-08.json b/common/changes/@visactor/vtable/feat-package-size_2024-07-01-07-08.json new file mode 100644 index 000000000..b30ef2bad --- /dev/null +++ b/common/changes/@visactor/vtable/feat-package-size_2024-07-01-07-08.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: optimize package size & add load on demand feature", + "type": "minor" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 156d9625e..2b8ada8ae 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -292,6 +292,7 @@ importers: '@visactor/vscale': ~0.18.1 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~0.18.9 + '@visactor/vutils-extension': ~1.11.5 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 chai: 4.3.4 @@ -336,6 +337,7 @@ importers: '@visactor/vscale': 0.18.9 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 0.18.9 + '@visactor/vutils-extension': 1.11.5 cssfontparser: 1.2.1 devDependencies: '@babel/core': 7.20.12 @@ -3819,6 +3821,13 @@ packages: '@visactor/vdataset': 0.18.9 '@visactor/vutils': 0.18.9 + /@visactor/vutils-extension/1.11.5: + resolution: {integrity: sha512-FDTFOsEB3AIsXJQJH8reH3FWfNpXkhvTPiaGez4OFy0i7iWBzN74PDvKZmSDImQCWgfVeo4KWz9Jvl3qZO1tSw==} + dependencies: + '@visactor/vdataset': 0.18.9 + '@visactor/vutils': 0.18.9 + dev: false + /@visactor/vutils/0.18.9: resolution: {integrity: sha512-+CPwBATTQUPtXQ0KVXFRz8SCwAY9m5aR9QmtsVqya+mgaay3moFaAPNTbdkLBuZM5ewRYVcv/3fsDxuH+NXfFg==} dependencies: diff --git a/docs/assets/guide/en/Load_on_Demand.md b/docs/assets/guide/en/Load_on_Demand.md new file mode 100644 index 000000000..c004ec40e --- /dev/null +++ b/docs/assets/guide/en/Load_on_Demand.md @@ -0,0 +1,38 @@ +# VTable on-demand loading + +By default, `ListTable`, `PivotTable` and `PivotChart` introduced from `@visactor/vtable` package contain all table-related components, which is a complete table component library. + +In order to meet the needs of package size optimization, VTable provides two types, `ListTableSimple` and `PivotTableSimple`, which are the most simplified lists and pivot tables, respectively. They only support text display and do not contain external components such as menus and titles. If you need some functions, you can load them on demand. The usage is as follows: + +```js +// ListTableSimple, PivotTableSimple are the simplest list and pivot table components, which do not include cell types and any components other than text +import {ListTableSimple, PivotTableSimple, registerTitle, registerTooltip} from '@visactor/vtable'; + +// Register title component +registerTitle(); + +// Register tooltip component +registerTooltip(); +``` + +## Load functions on demand + +### Functional components + +* registerAxis: axis component +* registerEmptyTip: empty prompt component +* registerLegend: legend component +* registerMenu: menu component +* registerTitle: title component +* registerTooltip: tooltip component + +### Cell type + +* registerChartCell: chart cell +* registerCheckboxCell: checkbox cell +* registerImageCell: Image cell +* registerProgressBarCell: Progress bar cell +* registerRadioCell: Radio button cell +* registerSparkLineCell: Sparkline cell +* registerTextCell: Text cell +* registerVideoCell: Video cell \ No newline at end of file diff --git a/docs/assets/guide/menu.json b/docs/assets/guide/menu.json index 9f5a0d88e..83d1b12f0 100644 --- a/docs/assets/guide/menu.json +++ b/docs/assets/guide/menu.json @@ -551,6 +551,13 @@ } ] }, + { + "path": "Load_on_Demand", + "title": { + "zh": "按需加载", + "en": "Load on Demand" + } + }, { "path": "search", "title": { diff --git a/docs/assets/guide/zh/Load_on_Demand.md b/docs/assets/guide/zh/Load_on_Demand.md new file mode 100644 index 000000000..3f834daa3 --- /dev/null +++ b/docs/assets/guide/zh/Load_on_Demand.md @@ -0,0 +1,38 @@ +# VTable 按需加载 + +默认从 `@visactor/vtable` 包中引入的 `ListTable` 、 `PivotTable` 和 `PivotChart` 包含所有的表格相关的组件,是一个完整的表格组件库。 + +为了满足包体积优化的需求,VTable提供了 `ListTableSimple` 和 `PivotTableSimple` 两个类型,分别是最简化的列表和透视表,只支持文字类型的显示,不包含菜单、标题等外部组件。如果需要部分功能,可以进行按需加载,使用方法如下: + +```js +// ListTableSimple, PivotTableSimple 是最简单的列表和透视表组件,不包除了文字之外的单元格类型和任何组件 +import {ListTableSimple, PivotTableSimple, registerTitle, registerTooltip} from '@visactor/vtable'; + +// 注册标题组件 +registerTitle(); + +// 注册tooltip组件 +registerTooltip(); +``` + +## 按需加载功能 + +### 功能组件 + +* registerAxis: 坐标轴组件 +* registerEmptyTip: 空白提示组件 +* registerLegend: 图例组件 +* registerMenu: 菜单组件 +* registerTitle: 标题组件 +* registerTooltip: tooltip组件 + +### 单元格类型 + +* registerChartCell: 图表单元格 +* registerCheckboxCell: 复选框单元格 +* registerImageCell: 图片单元格 +* registerProgressBarCell: 进度条单元格 +* registerRadioCell: 单选框单元格 +* registerSparkLineCell: 迷你图单元格 +* registerTextCell: 文字单元格 +* registerVideoCell: 视频单元格 \ No newline at end of file diff --git a/packages/vtable/__tests__/api/listTable-getCellRect.test.ts b/packages/vtable/__tests__/api/listTable-getCellRect.test.ts index e304c94d5..dad3cca5d 100644 --- a/packages/vtable/__tests__/api/listTable-getCellRect.test.ts +++ b/packages/vtable/__tests__/api/listTable-getCellRect.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable getCellRect test', () => { diff --git a/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts b/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts index 5dbcde10a..900f3ebbf 100644 --- a/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts +++ b/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable getCellRect test', () => { diff --git a/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts b/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts index f72000e6f..6d6012798 100644 --- a/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts +++ b/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-cellType-function init test', () => { diff --git a/packages/vtable/__tests__/columns/listTable-cellType.test.ts b/packages/vtable/__tests__/columns/listTable-cellType.test.ts index 66e41abc1..f1629a7e9 100644 --- a/packages/vtable/__tests__/columns/listTable-cellType.test.ts +++ b/packages/vtable/__tests__/columns/listTable-cellType.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-cellType init test', () => { diff --git a/packages/vtable/__tests__/columns/listTable-checkbox.test.ts b/packages/vtable/__tests__/columns/listTable-checkbox.test.ts index f8dea8c89..246245068 100644 --- a/packages/vtable/__tests__/columns/listTable-checkbox.test.ts +++ b/packages/vtable/__tests__/columns/listTable-checkbox.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-checkbox init test', () => { diff --git a/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts b/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts index ded17c8c0..5f39d66d4 100644 --- a/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts +++ b/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts @@ -1,7 +1,7 @@ /* eslint-disable max-len */ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import * as VTable from '../../src/index'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts b/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts index 03476fb4a..f7249a9e5 100644 --- a/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts +++ b/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; const generatePersons = count => { diff --git a/packages/vtable/__tests__/components/listTable-menu.test.ts b/packages/vtable/__tests__/components/listTable-menu.test.ts index 9c3f94cec..16eba25e5 100644 --- a/packages/vtable/__tests__/components/listTable-menu.test.ts +++ b/packages/vtable/__tests__/components/listTable-menu.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-menu init test', () => { diff --git a/packages/vtable/__tests__/components/listTable-title.test.ts b/packages/vtable/__tests__/components/listTable-title.test.ts index d90742892..aa0f73f55 100644 --- a/packages/vtable/__tests__/components/listTable-title.test.ts +++ b/packages/vtable/__tests__/components/listTable-title.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-title init test', () => { diff --git a/packages/vtable/__tests__/components/listTable-tooltip.test.ts b/packages/vtable/__tests__/components/listTable-tooltip.test.ts index 057c4d0a0..f378fd162 100644 --- a/packages/vtable/__tests__/components/listTable-tooltip.test.ts +++ b/packages/vtable/__tests__/components/listTable-tooltip.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import * as VTable from '../../src/index'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/edit/pivotTable.test.ts b/packages/vtable/__tests__/edit/pivotTable.test.ts index 29042df2b..e4820e3f2 100644 --- a/packages/vtable/__tests__/edit/pivotTable.test.ts +++ b/packages/vtable/__tests__/edit/pivotTable.test.ts @@ -2,7 +2,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from '../data/marketsales.json'; -import { PivotTable } from '../../src/PivotTable'; +import { PivotTable } from '../../src'; import { register } from '../../src'; import { InputEditor } from '@visactor/vtable-editors'; import { createDiv } from '../dom'; diff --git a/packages/vtable/__tests__/listTable-1W.test.ts b/packages/vtable/__tests__/listTable-1W.test.ts index c021d39e1..9c018758e 100644 --- a/packages/vtable/__tests__/listTable-1W.test.ts +++ b/packages/vtable/__tests__/listTable-1W.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../src/ListTable'; +import { ListTable } from '../src'; import * as VTable from '../src/index'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/listTable.test.ts b/packages/vtable/__tests__/listTable.test.ts index b4215bcaf..d76fc9508 100644 --- a/packages/vtable/__tests__/listTable.test.ts +++ b/packages/vtable/__tests__/listTable.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from './data/marketsales.json'; -import { ListTable } from '../src/ListTable'; +import { ListTable } from '../src'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('listTable init test', () => { diff --git a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts index b4f5d8240..efc31f54c 100644 --- a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts +++ b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable init test', () => { diff --git a/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts b/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts index 58d100e07..a65b85c7d 100644 --- a/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts +++ b/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv, removeDom } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-autoRowHeight init test', () => { diff --git a/packages/vtable/__tests__/options/listTable-frozen.test.ts b/packages/vtable/__tests__/options/listTable-frozen.test.ts index b11506591..47ed49543 100644 --- a/packages/vtable/__tests__/options/listTable-frozen.test.ts +++ b/packages/vtable/__tests__/options/listTable-frozen.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-frozen init test', () => { diff --git a/packages/vtable/__tests__/options/listTable-sort.test.ts b/packages/vtable/__tests__/options/listTable-sort.test.ts index 8f956ac64..fcf83b756 100644 --- a/packages/vtable/__tests__/options/listTable-sort.test.ts +++ b/packages/vtable/__tests__/options/listTable-sort.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src/ListTable'; +import { ListTable } from '../../src'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable init test', () => { diff --git a/packages/vtable/__tests__/pivotTable-analysis.test.ts b/packages/vtable/__tests__/pivotTable-analysis.test.ts index 37ceeaaba..ffff4f483 100644 --- a/packages/vtable/__tests__/pivotTable-analysis.test.ts +++ b/packages/vtable/__tests__/pivotTable-analysis.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/marketsales.json'; -import { PivotTable } from '../src/PivotTable'; +import { PivotTable } from '../src'; import * as VTable from '../src/index'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/pivotTable-tree.test.ts b/packages/vtable/__tests__/pivotTable-tree.test.ts index be6143c2f..38531f7c2 100644 --- a/packages/vtable/__tests__/pivotTable-tree.test.ts +++ b/packages/vtable/__tests__/pivotTable-tree.test.ts @@ -2,7 +2,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/North_American_Superstore_pivot_extension_rows.json'; -import { PivotTable } from '../src/PivotTable'; +import { PivotTable } from '../src'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('pivotTableTree init test', () => { diff --git a/packages/vtable/__tests__/pivotTable.test.ts b/packages/vtable/__tests__/pivotTable.test.ts index 8f0dde9ee..9fcf5b10c 100644 --- a/packages/vtable/__tests__/pivotTable.test.ts +++ b/packages/vtable/__tests__/pivotTable.test.ts @@ -2,7 +2,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/marketsales.json'; -import { PivotTable } from '../src/PivotTable'; +import { PivotTable } from '../src'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('pivotTable init test', () => { diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 0b5984752..55ef11030 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -19,7 +19,15 @@ "url": "https://VisActor.io/" }, "license": "MIT", - "sideEffects": true, + "sideEffects": [ + "./src/ListTable-all.js", + "./src/ListTable-simple.js", + "./src/PivotTable-all.js", + "./src/PivotTable-simple.js", + "./src/PivotChart.js", + "./src/index.js", + "./src/scenegraph/scenegraph.js" + ], "main": "cjs/index.js", "module": "es/index.js", "types": "es/index.d.ts", @@ -56,6 +64,7 @@ "@visactor/vutils": "~0.18.9", "@visactor/vscale": "~0.18.1", "@visactor/vdataset": "~0.18.1", + "@visactor/vutils-extension": "~1.11.5", "cssfontparser": "^1.2.1" }, "devDependencies": { @@ -123,4 +132,4 @@ "url": "https://github.com/VisActor/VTable.git", "directory": "packages/vtable" } -} +} \ No newline at end of file diff --git a/packages/vtable/src/ListTable-all.ts b/packages/vtable/src/ListTable-all.ts new file mode 100644 index 000000000..2d497ce21 --- /dev/null +++ b/packages/vtable/src/ListTable-all.ts @@ -0,0 +1,36 @@ +import { ListTable } from './ListTable'; +import { + registerAxis, + registerEmptyTip, + registerLegend, + registerMenu, + registerTitle, + registerTooltip +} from './components'; +import { + registerChartCell, + registerCheckboxCell, + registerImageCell, + registerProgressBarCell, + registerRadioCell, + registerSparkLineCell, + registerTextCell, + registerVideoCell +} from './scenegraph/group-creater/cell-type'; + +registerAxis(); +registerEmptyTip(); +registerLegend(); +registerMenu(); +registerTitle(); +registerTooltip(); + +registerChartCell(); +registerCheckboxCell(); +registerImageCell(); +registerProgressBarCell(); +registerRadioCell(); +registerSparkLineCell(); +registerTextCell(); +registerVideoCell(); +export class ListTableAll extends ListTable {} diff --git a/packages/vtable/src/ListTable-simple.ts b/packages/vtable/src/ListTable-simple.ts new file mode 100644 index 000000000..77d2e735e --- /dev/null +++ b/packages/vtable/src/ListTable-simple.ts @@ -0,0 +1,5 @@ +import { ListTable } from './ListTable'; +import { registerTextCell } from './scenegraph/group-creater/cell-type'; + +registerTextCell(); +export class ListTableSimple extends ListTable {} diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 86f20836c..b28f24b50 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -18,15 +18,13 @@ import type { } from './ts-types'; import { HierarchyState } from './ts-types'; import { SimpleHeaderLayoutMap } from './layout'; -import { isNumber, isObject, isValid } from '@visactor/vutils'; +import { isValid } from '@visactor/vutils'; import { _setDataSource, _setRecords, sortRecords } from './core/tableHelper'; import { BaseTable } from './core'; import type { BaseTableAPI, ListTableProtected } from './ts-types/base-table'; import { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; -import { Title } from './components/title/title'; -import { cloneDeep } from '@visactor/vutils'; +import type { ITitleComponent } from './components/title/title'; import { Env } from './tools/env'; -import { editor } from './register'; import * as editors from './edit/editors'; import { EditManeger } from './edit/edit-manager'; import { computeColWidth } from './scenegraph/layout/compute-col-width'; @@ -35,9 +33,44 @@ import { defaultOrderFn } from './tools/util'; import type { IEditor } from '@visactor/vtable-editors'; import type { ColumnData, ColumnDefine } from './ts-types/list-table/layout-map/api'; import { getCellRadioState, setCellRadioState } from './state/radio/radio'; -import { cloneDeepSpec } from '@vutils-extension'; +import { cloneDeepSpec } from '@visactor/vutils-extension'; import { setCellCheckboxState } from './state/checkbox/checkbox'; -import { EmptyTip } from './components/empty-tip/empty-tip'; +import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; +import { Factory } from './core/factory'; +// import { +// registerAxis, +// registerEmptyTip, +// registerLegend, +// registerMenu, +// registerTitle, +// registerTooltip +// } from './components'; +// import { +// registerChartCell, +// registerCheckboxCell, +// registerImageCell, +// registerProgressBarCell, +// registerRadioCell, +// registerSparkLineCell, +// registerTextCell, +// registerVideoCell +// } from './scenegraph/group-creater/cell-type'; + +// registerAxis(); +// registerEmptyTip(); +// registerLegend(); +// registerMenu(); +// registerTitle(); +// registerTooltip(); + +// registerChartCell(); +// registerCheckboxCell(); +// registerImageCell(); +// registerProgressBarCell(); +// registerRadioCell(); +// registerSparkLineCell(); +// registerTextCell(); +// registerVideoCell(); export class ListTable extends BaseTable implements ListTableAPI { declare internalProps: ListTableProtected; @@ -98,6 +131,7 @@ export class ListTable extends BaseTable implements ListTableAPI { this.setRecords([]); } if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -105,6 +139,7 @@ export class ListTable extends BaseTable implements ListTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } @@ -436,6 +471,7 @@ export class ListTable extends BaseTable implements ListTableAPI { this.render(); } if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -443,6 +479,7 @@ export class ListTable extends BaseTable implements ListTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } @@ -1037,6 +1074,7 @@ export class ListTable extends BaseTable implements ListTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } diff --git a/packages/vtable/src/PivotChart.ts b/packages/vtable/src/PivotChart.ts index 3bfe1f8a2..8973569dc 100644 --- a/packages/vtable/src/PivotChart.ts +++ b/packages/vtable/src/PivotChart.ts @@ -38,17 +38,53 @@ import { clearChartCacheImage, updateChartData } from './scenegraph/refresh-node import type { ITableAxisOption } from './ts-types/component/axis'; import { cloneDeep, isArray } from '@visactor/vutils'; import type { DiscreteLegend } from '@visactor/vrender-components'; -import { Title } from './components/title/title'; +import type { ITitleComponent } from './components/title/title'; import { Env } from './tools/env'; import { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; import type { IndicatorData } from './ts-types/list-table/layout-map/api'; -import { cloneDeepSpec } from '@vutils-extension'; +import { cloneDeepSpec } from '@visactor/vutils-extension'; import type { ITreeLayoutHeadNode } from './layout/tree-helper'; import { DimensionTree, type LayouTreeNode } from './layout/tree-helper'; import { IndicatorDimensionKeyPlaceholder } from './tools/global'; import { checkHasCartesianChart } from './layout/chart-helper/get-chart-spec'; import { supplementIndicatorNodesForCustomTree } from './layout/layout-helper'; -import { EmptyTip } from './components/empty-tip/empty-tip'; +import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; +import { Factory } from './core/factory'; +import { + registerAxis, + registerEmptyTip, + registerLegend, + registerMenu, + registerTitle, + registerTooltip +} from './components'; +import { + registerChartCell, + registerCheckboxCell, + registerImageCell, + registerProgressBarCell, + registerRadioCell, + registerSparkLineCell, + registerTextCell, + registerVideoCell +} from './scenegraph/group-creater/cell-type'; + +registerAxis(); +registerEmptyTip(); +registerLegend(); +registerMenu(); +registerTitle(); +registerTooltip(); + +registerChartCell(); +registerCheckboxCell(); +registerImageCell(); +registerProgressBarCell(); +registerRadioCell(); +registerSparkLineCell(); +registerTextCell(); +registerVideoCell(); + export class PivotChart extends BaseTable implements PivotChartAPI { layoutNodeId: { seqId: number } = { seqId: 0 }; declare internalProps: PivotChartProtected; @@ -228,6 +264,7 @@ export class PivotChart extends BaseTable implements PivotChartAPI { // 生成单元格场景树 this.scenegraph.createSceneGraph(); if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -235,6 +272,7 @@ export class PivotChart extends BaseTable implements PivotChartAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } @@ -460,6 +498,7 @@ export class PivotChart extends BaseTable implements PivotChartAPI { // 生成单元格场景树 this.scenegraph.createSceneGraph(); if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -467,6 +506,7 @@ export class PivotChart extends BaseTable implements PivotChartAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } diff --git a/packages/vtable/src/PivotTable-all.ts b/packages/vtable/src/PivotTable-all.ts new file mode 100644 index 000000000..caafdc0ed --- /dev/null +++ b/packages/vtable/src/PivotTable-all.ts @@ -0,0 +1,37 @@ +import { PivotTable } from './PivotTable'; +import { + registerAxis, + registerEmptyTip, + registerLegend, + registerMenu, + registerTitle, + registerTooltip +} from './components'; +import { + registerChartCell, + registerCheckboxCell, + registerImageCell, + registerProgressBarCell, + registerRadioCell, + registerSparkLineCell, + registerTextCell, + registerVideoCell +} from './scenegraph/group-creater/cell-type'; + +registerAxis(); +registerEmptyTip(); +registerLegend(); +registerMenu(); +registerTitle(); +registerTooltip(); + +registerChartCell(); +registerCheckboxCell(); +registerImageCell(); +registerProgressBarCell(); +registerRadioCell(); +registerSparkLineCell(); +registerTextCell(); +registerVideoCell(); + +export class PivotTableAll extends PivotTable {} diff --git a/packages/vtable/src/PivotTable-simple.ts b/packages/vtable/src/PivotTable-simple.ts new file mode 100644 index 000000000..f95c2e2a1 --- /dev/null +++ b/packages/vtable/src/PivotTable-simple.ts @@ -0,0 +1,6 @@ +import { PivotTable } from './PivotTable'; +import { registerTextCell } from './scenegraph/group-creater/cell-type'; + +registerTextCell(); + +export class PivotTableSimple extends PivotTable {} diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index b190bcbc9..44fa6e68d 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -28,7 +28,7 @@ import { cellInRange, emptyFn } from './tools/helper'; import { Dataset } from './dataset/dataset'; import { BaseTable } from './core/BaseTable'; import type { BaseTableAPI, HeaderData, PivotTableProtected } from './ts-types/base-table'; -import { Title } from './components/title/title'; +import type { ITitleComponent } from './components/title/title'; import { cloneDeep, isNumber, isValid } from '@visactor/vutils'; import { Env } from './tools/env'; import type { ITreeLayoutHeadNode } from './layout/tree-helper'; @@ -41,9 +41,11 @@ import { computeColWidth } from './scenegraph/layout/compute-col-width'; import { computeRowHeight } from './scenegraph/layout/compute-row-height'; import { isAllDigits } from './tools/util'; import type { IndicatorData } from './ts-types/list-table/layout-map/api'; -import { cloneDeepSpec } from '@vutils-extension'; +import { cloneDeepSpec } from '@visactor/vutils-extension'; import { parseColKeyRowKeyForPivotTable, supplementIndicatorNodesForCustomTree } from './layout/layout-helper'; -import { EmptyTip } from './components/empty-tip/empty-tip'; +import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; +import { Factory } from './core/factory'; + export class PivotTable extends BaseTable implements PivotTableAPI { layoutNodeId: { seqId: number } = { seqId: 0 }; declare internalProps: PivotTableProtected; @@ -207,6 +209,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { // this.render(); if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -214,6 +217,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } @@ -417,6 +421,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { // this.scenegraph.resize(); // } if (options.title) { + const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } @@ -424,6 +429,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } @@ -1560,6 +1566,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (this.internalProps.emptyTip) { this.internalProps.emptyTip.resetVisible(); } else { + const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); this.internalProps.emptyTip.resetVisible(); } diff --git a/packages/vtable/src/components/axis/axis.ts b/packages/vtable/src/components/axis/axis.ts index 3dcf9b23e..2cd5bd4ca 100644 --- a/packages/vtable/src/components/axis/axis.ts +++ b/packages/vtable/src/components/axis/axis.ts @@ -2,15 +2,15 @@ import { degreeToRadian, isNil, isValidNumber, merge } from '@visactor/vutils'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { ICellAxisOption } from '../../ts-types/component/axis'; import { LineAxis, type LineAxisAttributes } from '@visactor/vrender-components'; -import { commonAxis, getAxisAttributes, getCommonAxis } from './get-axis-attributes'; +import { getAxisAttributes, getCommonAxis } from './get-axis-attributes'; import { isXAxis, isYAxis } from '../util/orient'; import type { IOrientType } from '../../ts-types/component/util'; import { BandAxisScale } from './band-scale'; import { registerDataSetInstanceParser, registerDataSetInstanceTransform } from '../util/register'; import type { Parser } from '@visactor/vdataset'; -import { DataView } from '@visactor/vdataset'; +import { DataSet, DataView } from '@visactor/vdataset'; import type { IBaseScale } from '@visactor/vscale'; -import { ticks } from '@vutils-extension'; +import { ticks } from '@src/vrender'; import { LinearAxisScale } from './linear-scale'; import { doOverlap } from './label-overlap'; import type { TableTheme } from '../../themes/theme'; @@ -21,6 +21,16 @@ const scaleParser: Parser = (scale: IBaseScale) => { return scale; }; +export interface ICartesianAxis { + new ( + option: ICellAxisOption, + width: number, + height: number, + padding: [number, number, number, number], + table: BaseTableAPI + ): CartesianAxis; +} + export class CartesianAxis { width: number; height: number; @@ -113,11 +123,16 @@ export class CartesianAxis { } initData() { + if (!this.table._vDataSet) { + this.table._vDataSet = new DataSet(); + } + registerDataSetInstanceParser(this.table._vDataSet, 'scale', scaleParser); registerDataSetInstanceTransform(this.table._vDataSet, 'ticks', ticks); const label = this.option.label || {}; const tick = this.option.tick || {}; + const tickData = new DataView(this.table._vDataSet) .parse(this.scale._scale, { type: 'scale' diff --git a/packages/vtable/src/components/axis/get-axis-component-size.ts b/packages/vtable/src/components/axis/get-axis-component-size.ts index 7e27f917f..3c11cac29 100644 --- a/packages/vtable/src/components/axis/get-axis-component-size.ts +++ b/packages/vtable/src/components/axis/get-axis-component-size.ts @@ -3,6 +3,8 @@ import type { BaseTableAPI } from '../../ts-types/base-table'; import type { ICellAxisOption } from '../../ts-types/component/axis'; import { DEFAULT_TEXT_FONT_FAMILY, DEFAULT_TEXT_FONT_SIZE, commonAxis } from './get-axis-attributes'; +export type ComputeAxisComponentWidth = (config: ICellAxisOption, table: BaseTableAPI) => number; +export type ComputeAxisComponentHeight = (config: ICellAxisOption, table: BaseTableAPI) => number; /** * @description: compuational vertical axis width * @param {ICellAxisOption} config diff --git a/packages/vtable/src/components/empty-tip/empty-tip.ts b/packages/vtable/src/components/empty-tip/empty-tip.ts index 971b61d8a..f5a0a55c6 100644 --- a/packages/vtable/src/components/empty-tip/empty-tip.ts +++ b/packages/vtable/src/components/empty-tip/empty-tip.ts @@ -9,6 +9,10 @@ import type { PivotTable } from '../../PivotTable'; const emptyTipSvg = ''; +export interface IEmptyTipComponent { + new (emptyTipOption: IEmptyTip | true, table: BaseTableAPI): EmptyTip; +} + export class EmptyTip { table: BaseTableAPI; _emptyTipOption: IEmptyTip = { diff --git a/packages/vtable/src/components/index.ts b/packages/vtable/src/components/index.ts new file mode 100644 index 000000000..546696748 --- /dev/null +++ b/packages/vtable/src/components/index.ts @@ -0,0 +1,36 @@ +import { Factory } from '../core/factory'; +import { getAxisConfigInPivotChart } from '../layout/chart-helper/get-axis-config'; +import { CartesianAxis } from './axis/axis'; +import { computeAxisComponentHeight, computeAxisComponentWidth } from './axis/get-axis-component-size'; +import { EmptyTip } from './empty-tip/empty-tip'; +import { createLegend } from './legend/create-legend'; +import { MenuHandler } from './menu/dom/MenuHandler'; +import { Title } from './title/title'; +import { TooltipHandler } from './tooltip/TooltipHandler'; + +export const registerAxis = () => { + Factory.registerComponent('axis', CartesianAxis); + Factory.registerFunction('computeAxisComponentWidth', computeAxisComponentWidth); + Factory.registerFunction('computeAxisComponentHeight', computeAxisComponentHeight); + Factory.registerFunction('getAxisConfigInPivotChart', getAxisConfigInPivotChart); +}; + +export const registerEmptyTip = () => { + Factory.registerComponent('emptyTip', EmptyTip); +}; + +export const registerLegend = () => { + Factory.registerFunction('createLegend', createLegend); +}; + +export const registerMenu = () => { + Factory.registerComponent('menuHandler', MenuHandler); +}; + +export const registerTitle = () => { + Factory.registerComponent('title', Title); +}; + +export const registerTooltip = () => { + Factory.registerComponent('tooltipHandler', TooltipHandler); +}; diff --git a/packages/vtable/src/components/legend/create-legend.ts b/packages/vtable/src/components/legend/create-legend.ts index 25bc710c6..4665f3aec 100644 --- a/packages/vtable/src/components/legend/create-legend.ts +++ b/packages/vtable/src/components/legend/create-legend.ts @@ -3,6 +3,10 @@ import { DiscreteTableLegend } from './discrete-legend/discrete-legend'; import type { BaseTableAPI } from '../../ts-types/base-table'; import { ContinueTableLegend } from './continue-legend/continue-legend'; +export type CreateLegend = ( + option: ITableLegendOption, + table: BaseTableAPI +) => DiscreteTableLegend | ContinueTableLegend; export function createLegend(option: ITableLegendOption, table: BaseTableAPI) { if (option.type === 'color' || option.type === 'size') { return new ContinueTableLegend(option, table); diff --git a/packages/vtable/src/components/menu/dom/MenuHandler.ts b/packages/vtable/src/components/menu/dom/MenuHandler.ts index 70dafeb62..5e4cbb349 100644 --- a/packages/vtable/src/components/menu/dom/MenuHandler.ts +++ b/packages/vtable/src/components/menu/dom/MenuHandler.ts @@ -115,6 +115,9 @@ type AttachInfo = { range: CellRange; }; +export interface IMenuHandler { + new (table: BaseTableAPI): MenuHandler; +} export class MenuHandler { private _table: BaseTableAPI; private _menuInstances?: { [type: string]: BaseMenu }; diff --git a/packages/vtable/src/components/title/title.ts b/packages/vtable/src/components/title/title.ts index a0fcd07c7..1930a72ea 100644 --- a/packages/vtable/src/components/title/title.ts +++ b/packages/vtable/src/components/title/title.ts @@ -5,6 +5,10 @@ import type { ITitle } from '../../ts-types/component/title'; import { getQuadProps } from '../../scenegraph/utils/padding'; import type { BaseTableAPI } from '../../ts-types/base-table'; import { isEqual } from '@visactor/vutils'; + +export interface ITitleComponent { + new (titleOption: ITitle, table: BaseTableAPI): Title; +} export class Title { table: BaseTableAPI; _titleOption: ITitle; diff --git a/packages/vtable/src/components/tooltip/TooltipHandler.ts b/packages/vtable/src/components/tooltip/TooltipHandler.ts index 89afbf690..6ba0568ca 100644 --- a/packages/vtable/src/components/tooltip/TooltipHandler.ts +++ b/packages/vtable/src/components/tooltip/TooltipHandler.ts @@ -21,6 +21,9 @@ type AttachInfo = { range: CellRange; tooltipOptions: TooltipOptions; }; +export interface ITooltipHandler { + new (table: BaseTableAPI, confine: boolean): TooltipHandler; +} export class TooltipHandler { private _table: BaseTableAPI; diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 8d61bd60d..04a5f6fc9 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -70,7 +70,7 @@ import { EventManager } from '../event/event'; import { BodyHelper } from '../body-helper/body-helper'; import { HeaderHelper } from '../header-helper/header-helper'; import type { PivotHeaderLayoutMap } from '../layout/pivot-header-layout'; -import { TooltipHandler } from '../components/tooltip/TooltipHandler'; +import type { ITooltipHandler } from '../components/tooltip/TooltipHandler'; import type { CachedDataSource, DataSource } from '../data'; import { AABBBounds, @@ -104,7 +104,7 @@ import { getStyleTheme, updateRootElementPadding } from './tableHelper'; -import { MenuHandler } from '../components/menu/dom/MenuHandler'; +import type { IMenuHandler } from '../components/menu/dom/MenuHandler'; import type { BaseTableAPI, BaseTableConstructorOptions, @@ -113,8 +113,8 @@ import type { } from '../ts-types/base-table'; import { FocusInput } from './FouseInput'; import { defaultPixelRatio } from '../tools/pixel-ratio'; -import { createLegend } from '../components/legend/create-legend'; -import { DataSet } from '@visactor/vdataset'; +import type { CreateLegend } from '../components/legend/create-legend'; +import type { DataSet } from '@visactor/vdataset'; import { Title } from '../components/title/title'; import type { Chart } from '../scenegraph/graphic/chart'; import { setBatchRenderChartCount } from '../scenegraph/graphic/contributions/chart-render-helper'; @@ -129,6 +129,7 @@ import type { ITextGraphicAttribute } from '@src/vrender'; import { ReactCustomLayout } from '../components/react/react-custom-layout'; import type { ISortedMapItem } from '../data/DataSource'; import { hasAutoImageColumn } from '../layout/layout-helper'; +import { Factory } from './factory'; import { getCellAt, getCellAtRelativePosition, @@ -167,7 +168,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { canvasWidth?: number; canvasHeight?: number; - _vDataSet: DataSet; + _vDataSet?: DataSet; scenegraph: Scenegraph; stateManager: StateManager; eventManager: EventManager; @@ -414,13 +415,14 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { : 0 : 10; // 生成scenegraph - this._vDataSet = new DataSet(); + // this._vDataSet = new DataSet(); this.scenegraph = new Scenegraph(this); this.stateManager = new StateManager(this); this.eventManager = new EventManager(this); if (options.legends) { internalProps.legends = []; + const createLegend = Factory.getFunction('createLegend') as CreateLegend; if (Array.isArray(options.legends)) { for (let i = 0; i < options.legends.length; i++) { internalProps.legends.push(createLegend(options.legends[i], this)); @@ -448,6 +450,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { options.tooltip ); if (internalProps.tooltip.renderMode === 'html') { + const TooltipHandler = Factory.getComponent('tooltipHandler') as ITooltipHandler; internalProps.tooltipHandler = new TooltipHandler(this, internalProps.tooltip.confine); } internalProps.menu = Object.assign( @@ -464,6 +467,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { (this.globalDropDownMenu = options.menu.defaultHeaderMenuItems); if (internalProps.menu.renderMode === 'html') { + const MenuHandler = Factory.getComponent('menuHandler') as IMenuHandler; internalProps.menuHandler = new MenuHandler(this); } @@ -2261,7 +2265,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { : 0 : 10; // 生成scenegraph - this._vDataSet = new DataSet(); + // this._vDataSet = new DataSet(); internalProps.legends?.forEach(legend => { legend?.release(); }); @@ -2280,6 +2284,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { this.eventManager.updateEventBinder(); if (options.legends) { internalProps.legends = []; + const createLegend = Factory.getFunction('createLegend') as CreateLegend; if (Array.isArray(options.legends)) { for (let i = 0; i < options.legends.length; i++) { internalProps.legends.push(createLegend(options.legends[i], this)); @@ -2312,6 +2317,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { options.tooltip ); if (internalProps.tooltip.renderMode === 'html' && !internalProps.tooltipHandler) { + const TooltipHandler = Factory.getComponent('tooltipHandler') as ITooltipHandler; internalProps.tooltipHandler = new TooltipHandler(this, internalProps.tooltip.confine); } @@ -2330,6 +2336,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { (this.globalDropDownMenu = options.menu.defaultHeaderMenuItems); if (internalProps.menu.renderMode === 'html' && !internalProps.menuHandler) { + const MenuHandler = Factory.getComponent('menuHandler') as IMenuHandler; internalProps.menuHandler = new MenuHandler(this); } this.clearCellStyleCache(); diff --git a/packages/vtable/src/core/factory.ts b/packages/vtable/src/core/factory.ts new file mode 100644 index 000000000..91fa95eb7 --- /dev/null +++ b/packages/vtable/src/core/factory.ts @@ -0,0 +1,29 @@ +export class Factory { + private static _components: { [key: string]: any } = {}; + private static _functions: { [key: string]: any } = {}; + private static _cellTypes: { [key: string]: any } = {}; + + static registerComponent(key: string, component: any) { + Factory._components[key] = component; + } + + static getComponent(key: string) { + return Factory._components[key]; + } + + static registerFunction(key: string, func: any) { + Factory._functions[key] = func; + } + + static getFunction(key: string) { + return Factory._functions[key]; + } + + static registerCellType(key: string, cellType: any) { + Factory._cellTypes[key] = cellType; + } + + static getCellType(key: string) { + return Factory._cellTypes[key]; + } +} diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index de9582877..2928eca9e 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -30,8 +30,11 @@ import type { TextAlignType, TextBaselineType } from './ts-types'; -import { ListTable } from './ListTable'; -import { PivotTable } from './PivotTable'; +import { ListTableAll as ListTable } from './ListTable-all'; +import { ListTableSimple } from './ListTable-simple'; +// import { PivotTable } from './PivotTable'; +import { PivotTableAll as PivotTable } from './PivotTable-all'; +import { PivotTableSimple } from './PivotTable-simple'; import { PivotChart } from './PivotChart'; import type { MousePointerCellEvent } from './ts-types/events'; import * as CustomLayout from './render/layout'; @@ -62,8 +65,10 @@ export { TYPES, core, ListTable, + ListTableSimple, ListTableConstructorOptions, PivotTable, + PivotTableSimple, PivotTableConstructorOptions, PivotChartConstructorOptions, PivotChart, @@ -116,3 +121,6 @@ function clearGlobal() { // columns.type.clearGlobal(); } TYPES.AggregationType; + +export * from './components'; +export * from './scenegraph/group-creater/cell-type'; diff --git a/packages/vtable/src/layout/chart-helper/get-axis-config.ts b/packages/vtable/src/layout/chart-helper/get-axis-config.ts index 6bf67ab11..d3d5439c4 100644 --- a/packages/vtable/src/layout/chart-helper/get-axis-config.ts +++ b/packages/vtable/src/layout/chart-helper/get-axis-config.ts @@ -2,10 +2,12 @@ import { isArray, isNumber, isValid, merge } from '@visactor/vutils'; import type { PivotHeaderLayoutMap } from '../pivot-header-layout'; import type { ITableAxisOption } from '../../ts-types/component/axis'; import type { PivotChart } from '../../PivotChart'; -import { getAxisDomainRangeAndLabels } from './get-axis-domain'; import type { CollectedValue } from '../../ts-types'; import { getNewRangeToAlign } from './zero-align'; +import { Factory } from '../../core/factory'; +import type { GetAxisDomainRangeAndLabels } from './get-axis-domain'; +export type GetAxisConfigInPivotChart = (col: number, row: number, layout: PivotHeaderLayoutMap) => any; export function getAxisConfigInPivotChart(col: number, row: number, layout: PivotHeaderLayoutMap): any { if (!layout._table.isPivotChart()) { return undefined; @@ -422,7 +424,7 @@ export function getAxisOption(col: number, row: number, orient: string, layout: }; } -export function checkZeroAlign(spec: any, orient: string, layout: PivotHeaderLayoutMap) { +function checkZeroAlign(spec: any, orient: string, layout: PivotHeaderLayoutMap) { // check condition: // 1. two axes and one set sync // 2. axisId in sync is another @@ -558,6 +560,7 @@ function getRange( range.min = range.min < 0 ? -1 : 0; range.max = range.max > 0 ? 1 : 0; } + const getAxisDomainRangeAndLabels = Factory.getFunction('getAxisDomainRangeAndLabels') as GetAxisDomainRangeAndLabels; const { range: niceRange, ticks } = getAxisDomainRangeAndLabels( range.min, range.max, diff --git a/packages/vtable/src/layout/chart-helper/get-axis-domain.ts b/packages/vtable/src/layout/chart-helper/get-axis-domain.ts index 0dbe96002..2e5e6cf23 100644 --- a/packages/vtable/src/layout/chart-helper/get-axis-domain.ts +++ b/packages/vtable/src/layout/chart-helper/get-axis-domain.ts @@ -89,3 +89,5 @@ export function getAxisDomainRangeAndLabels( ticks: scaleTicks }; } + +export type GetAxisDomainRangeAndLabels = typeof getAxisDomainRangeAndLabels; diff --git a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts index ef8c37c08..91c012394 100644 --- a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts +++ b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts @@ -2,10 +2,12 @@ import { cloneDeep, isArray, isNumber, merge } from '@visactor/vutils'; import type { PivotHeaderLayoutMap } from '../pivot-header-layout'; import type { SimpleHeaderLayoutMap } from '../simple-header-layout'; import { getAxisOption, getAxisRange } from './get-axis-config'; -import { getAxisDomainRangeAndLabels } from './get-axis-domain'; import { getNewRangeToAlign } from './zero-align'; import type { IChartIndicator, IIndicator } from '../../ts-types'; -import { cloneDeepSpec } from '@vutils-extension'; +import { cloneDeepSpec } from '@visactor/vutils-extension'; +import { Factory } from '../../core/factory'; +import type { GetAxisDomainRangeAndLabels } from './get-axis-domain'; +import { DEFAULT_TEXT_FONT_SIZE } from '../../components/axis/get-axis-attributes'; const NO_AXISID_FRO_VTABLE = 'NO_AXISID_FRO_VTABLE'; @@ -211,14 +213,15 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout axes.push( merge( { - range + range, + label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } }, axisOption, { type: axisOption?.type || 'linear', orient: index === 0 ? 'bottom' : 'top', // visible: true, - label: { visible: false }, + label: { visible: false, flush: true }, // label: { flush: true }, title: { visible: false }, domainLine: { visible: false }, @@ -246,7 +249,8 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout merge( { domain: chartType === 'scatter' && !Array.isArray(domain) ? undefined : Array.from(domain ?? []), - range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined + range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined, + label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } }, axisOption, { @@ -308,14 +312,15 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout axes.push( merge( { - range + range, + label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } }, axisOption, { type: axisOption?.type || 'linear', orient: index === 0 ? 'left' : 'right', // visible: true, - label: { visible: false }, + label: { visible: false, flush: true }, // label: { flush: true }, title: { visible: false }, domainLine: { visible: false }, @@ -345,7 +350,8 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout merge( { domain: chartType === 'scatter' && !Array.isArray(domain) ? undefined : Array.from(domain ?? []), - range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined + range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined, + label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } }, axisOption, { @@ -424,6 +430,9 @@ function getRange( range.max = Math.max(range.max, 0); } if (axisOption?.nice) { + const getAxisDomainRangeAndLabels = Factory.getFunction( + 'getAxisDomainRangeAndLabels' + ) as GetAxisDomainRangeAndLabels; const { range: axisRange } = getAxisDomainRangeAndLabels( range.min, range.max, diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 9e3785c51..1def71326 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -34,8 +34,6 @@ import type { PivotTable } from '../PivotTable'; import type { PivotChart } from '../PivotChart'; import { IndicatorDimensionKeyPlaceholder } from '../tools/global'; import { diffCellAddress } from '../tools/diff-cell'; -import type { ILinkDimension } from '../ts-types/pivot-table/dimension/link-dimension'; -import type { IImageDimension } from '../ts-types/pivot-table/dimension/image-dimension'; import { checkHasCartesianChart, checkHasChart, @@ -54,7 +52,8 @@ import { cloneDeep, isArray, isValid } from '@visactor/vutils'; import type { TextStyle } from '../body-helper/style'; import type { ITableAxisOption } from '../ts-types/component/axis'; import { getQuadProps } from '../scenegraph/utils/padding'; -import { getAxisConfigInPivotChart } from './chart-helper/get-axis-config'; +import type { GetAxisConfigInPivotChart } from './chart-helper/get-axis-config'; +import { Factory } from '../core/factory'; // export const sharedVar = { seqId: 0 }; // let colIndex = 0; @@ -2913,6 +2912,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ((this.isFrozenRow(col, row) || this.isBottomFrozenRow(col, row)) && isHasCartesianChartInline(col, row, 'col', this)) ) { + const getAxisConfigInPivotChart = Factory.getFunction('getAxisConfigInPivotChart') as GetAxisConfigInPivotChart; return getAxisConfigInPivotChart(col, row, this); } return undefined; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 133dbec09..756ef2074 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -8,7 +8,6 @@ import type { ColumnDefine, ColumnTypeOption, ImageColumnDefine, - MappingRule, ProgressbarColumnDefine, IRowSeriesNumber, TextColumnDefine, @@ -17,27 +16,25 @@ import type { import { dealWithCustom } from '../component/custom'; import type { Group } from '../graphic/group'; import { getProp } from '../utils/get-prop'; -import { createChartCellGroup } from './cell-type/chart-cell'; -import { createImageCellGroup } from './cell-type/image-cell'; -import { createProgressBarCell } from './cell-type/progress-bar-cell'; -import { createSparkLineCellGroup } from './cell-type/spark-line-cell'; -import { createCellGroup } from './cell-type/text-cell'; -import { createVideoCellGroup } from './cell-type/video-cell'; -import type { BaseTableAPI, HeaderData, PivotTableProtected } from '../../ts-types/base-table'; +import type { CreateChartCellGroup } from './cell-type/chart-cell'; +import type { CreateImageCellGroup } from './cell-type/image-cell'; +import type { CreateProgressBarCell } from './cell-type/progress-bar-cell'; +import type { CreateSparkLineCellGroup } from './cell-type/spark-line-cell'; +import type { CreateTextCellGroup } from './cell-type/text-cell'; +import type { CreateVideoCellGroup } from './cell-type/video-cell'; +import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; import { getCellCornerRadius, getStyleTheme } from '../../core/tableHelper'; import { isPromise } from '../../tools/helper'; import { dealPromiseData } from '../utils/deal-promise-data'; -import { CartesianAxis } from '../../components/axis/axis'; -import { createCheckboxCellGroup } from './cell-type/checkbox-cell'; -// import type { PivotLayoutMap } from '../../layout/pivot-layout'; -import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; +import type { ICartesianAxis } from '../../components/axis/axis'; +import { Factory } from '../../core/factory'; +import type { CreateCheckboxCellGroup } from './cell-type/checkbox-cell'; import { getHierarchyOffset } from '../utils/get-hierarchy-offset'; import { getQuadProps } from '../utils/padding'; -import { convertInternal } from '../../tools/util'; import { updateCellContentHeight, updateCellContentWidth } from '../utils/text-icon-layout'; import { isArray } from '@visactor/vutils'; import { breakString } from '../utils/break-string'; -import { createRadioCellGroup } from './cell-type/radio-cell'; +import type { CreateRadioCellGroup } from './cell-type/radio-cell'; export function createCell( type: ColumnTypeOption, @@ -164,7 +161,8 @@ export function createCell( } } - cellGroup = createCellGroup( + const createTextCellGroup = Factory.getFunction('createTextCellGroup') as CreateTextCellGroup; + cellGroup = createTextCellGroup( table, value, columnGroup, @@ -188,6 +186,7 @@ export function createCell( const axisConfig = table.internalProps.layoutMap.getAxisConfigInPivotChart(col, row); if (axisConfig) { + const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis(axisConfig, cellGroup.attribute.width, cellGroup.attribute.height, padding, table); cellGroup.clear(); cellGroup.appendChild(axis.component); @@ -203,6 +202,7 @@ export function createCell( } } else if (type === 'image') { // 创建图片单元格 + const createImageCellGroup = Factory.getFunction('createImageCellGroup') as CreateImageCellGroup; cellGroup = createImageCellGroup( columnGroup, 0, @@ -224,6 +224,7 @@ export function createCell( ); } else if (type === 'video') { // 创建视频单元格 + const createVideoCellGroup = Factory.getFunction('createVideoCellGroup') as CreateVideoCellGroup; cellGroup = createVideoCellGroup( columnGroup, 0, @@ -245,6 +246,7 @@ export function createCell( ); } else if (type === 'chart') { const chartInstance = table.internalProps.layoutMap.getChartInstance(col, row); + const createChartCellGroup = Factory.getFunction('createChartCellGroup') as CreateChartCellGroup; cellGroup = createChartCellGroup( null, columnGroup, @@ -269,7 +271,8 @@ export function createCell( const style = table._getCellStyle(col, row) as ProgressBarStyle; const dataValue = table.getCellOriginValue(col, row); // 创建基础文字单元格 - cellGroup = createCellGroup( + const createTextCellGroup = Factory.getFunction('createTextCellGroup') as CreateTextCellGroup; + cellGroup = createTextCellGroup( table, value, columnGroup, @@ -292,6 +295,7 @@ export function createCell( ); // 创建bar group + const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const progressBarGroup = createProgressBarCell( define as ProgressbarColumnDefine, style, @@ -310,6 +314,7 @@ export function createCell( cellGroup.appendChild(progressBarGroup); } } else if (type === 'sparkline') { + const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; cellGroup = createSparkLineCellGroup( null, columnGroup, @@ -325,6 +330,7 @@ export function createCell( isAsync ); } else if (type === 'checkbox') { + const createCheckboxCellGroup = Factory.getFunction('createCheckboxCellGroup') as CreateCheckboxCellGroup; cellGroup = createCheckboxCellGroup( null, columnGroup, @@ -346,6 +352,7 @@ export function createCell( isAsync ); } else if (type === 'radio') { + const createRadioCellGroup = Factory.getFunction('createRadioCellGroup') as CreateRadioCellGroup; cellGroup = createRadioCellGroup( null, columnGroup, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts index 35298652e..a5fdc3ad5 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts @@ -123,3 +123,5 @@ export function createChartCellGroup( return cellGroup; } + +export type CreateChartCellGroup = typeof createChartCellGroup; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts index c7afa2ab5..e85099cc0 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts @@ -1,6 +1,4 @@ -import type { ILine, ISymbol, IThemeSpec } from '@src/vrender'; -import { createLine, createSymbol } from '@src/vrender'; -import { PointScale, LinearScale } from '@visactor/vscale'; +import type { IThemeSpec } from '@src/vrender'; import { Group } from '../../graphic/group'; import type { CellInfo, CellRange, CheckboxColumnDefine, CheckboxStyleOption, SparklineSpec } from '../../../ts-types'; import type { BaseTableAPI } from '../../../ts-types/base-table'; @@ -300,3 +298,5 @@ function createCheckbox( return checkbox; } + +export type CreateCheckboxCellGroup = typeof createCheckboxCellGroup; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts index 352e7c178..6cb59600e 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts @@ -220,6 +220,8 @@ export function createImageCellGroup( return cellGroup; } +export type CreateImageCellGroup = typeof createImageCellGroup; + /** * 调整某个图片资源所在行列的行高列宽 之后重绘 * @param col diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts new file mode 100644 index 000000000..36930f41a --- /dev/null +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts @@ -0,0 +1,43 @@ +import { Factory } from '../../../core/factory'; +import { createChartCellGroup } from './chart-cell'; +import { createCheckboxCellGroup } from './checkbox-cell'; +import { createImageCellGroup } from './image-cell'; +import { createRadioCellGroup } from './radio-cell'; +import { createSparkLineCellGroup } from './spark-line-cell'; +import { createVideoCellGroup } from './video-cell'; +import { createCellGroup as createTextCellGroup } from './text-cell'; +import { createProgressBarCell } from './progress-bar-cell'; +import { getAxisDomainRangeAndLabels } from '../../../layout/chart-helper/get-axis-domain'; + +export const registerChartCell = () => { + Factory.registerFunction('createChartCellGroup', createChartCellGroup); + Factory.registerFunction('getAxisDomainRangeAndLabels', getAxisDomainRangeAndLabels); +}; + +export const registerCheckboxCell = () => { + Factory.registerFunction('createCheckboxCellGroup', createCheckboxCellGroup); +}; + +export const registerImageCell = () => { + Factory.registerFunction('createImageCellGroup', createImageCellGroup); +}; + +export const registerProgressBarCell = () => { + Factory.registerFunction('createProgressBarCell', createProgressBarCell); +}; + +export const registerRadioCell = () => { + Factory.registerFunction('createRadioCellGroup', createRadioCellGroup); +}; + +export const registerSparkLineCell = () => { + Factory.registerFunction('createSparkLineCellGroup', createSparkLineCellGroup); +}; + +export const registerTextCell = () => { + Factory.registerFunction('createTextCellGroup', createTextCellGroup); +}; + +export const registerVideoCell = () => { + Factory.registerFunction('createVideoCellGroup', createVideoCellGroup); +}; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts index a1e5bf61f..b19a32ddb 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts @@ -560,3 +560,5 @@ export function createProgressBarCell( } return percentCompleteBarGroup; } + +export type CreateProgressBarCell = typeof createProgressBarCell; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts index eb30a4449..e62c97f9a 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts @@ -98,6 +98,8 @@ export function createRadioCellGroup( return cellGroup; } +export type CreateRadioCellGroup = typeof createRadioCellGroup; + function createRadio( col: number, row: number, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts index 58dee58c5..a7fb271f8 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts @@ -85,6 +85,8 @@ export function createSparkLineCellGroup( return cellGroup; } +export type CreateSparkLineCellGroup = typeof createSparkLineCellGroup; + function createSparkLine( col: number, row: number, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts index 901d6afe6..c6cf7f6b3 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts @@ -179,6 +179,8 @@ export function createCellGroup( return cellGroup; } +export type CreateTextCellGroup = typeof createCellGroup; + // /** // * @description: 获取函数式赋值的样式,记录在cellTheme中 // * @param {BaseTableAPI} table diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts index 4b8bc8ecd..e2b024fa1 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts @@ -262,3 +262,5 @@ export function createVideoCellGroup( return cellGroup; } + +export type CreateVideoCellGroup = typeof createVideoCellGroup; diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index 2b828463c..f7031bad5 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -14,8 +14,8 @@ import { getQuadProps } from '../utils/padding'; import { getProp } from '../utils/get-prop'; import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; -import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; -import { computeAxisComponentWidth } from '../../components/axis/get-axis-component-size'; +import type { ComputeAxisComponentWidth } from '../../components/axis/get-axis-component-size'; +import { Factory } from '../../core/factory'; import { Group as VGroup } from '@src/vrender'; import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; @@ -301,8 +301,9 @@ function computeAutoColWidth( // 判断透视图轴组件 if (table.isPivotChart()) { const layout = table.internalProps.layoutMap as PivotHeaderLayoutMap; - const axisConfig = getAxisConfigInPivotChart(col, row, layout); + const axisConfig = layout.getAxisConfigInPivotChart(col, row); if (axisConfig) { + const computeAxisComponentWidth: ComputeAxisComponentWidth = Factory.getFunction('computeAxisComponentWidth'); const axisWidth = computeAxisComponentWidth(axisConfig, table); if (typeof axisWidth === 'number') { maxWidth = Math.max(axisWidth, maxWidth); diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index 6ddd91d55..8ae8a201f 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -8,8 +8,8 @@ import type { ColumnData, ColumnDefine, TextColumnDefine } from '../../ts-types/ import { getProp } from '../utils/get-prop'; import { getQuadProps } from '../utils/padding'; import { dealWithRichTextIcon } from '../utils/text-icon-layout'; -import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; -import { computeAxisComponentHeight } from '../../components/axis/get-axis-component-size'; +import type { ComputeAxisComponentHeight } from '../../components/axis/get-axis-component-size'; +import { Factory } from '../../core/factory'; import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; import { CheckBox } from '@visactor/vrender-components'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; @@ -351,8 +351,10 @@ export function computeRowHeight(row: number, startCol: number, endCol: number, // Axis component height calculation if (table.isPivotChart()) { const layout = table.internalProps.layoutMap as PivotHeaderLayoutMap; - const axisConfig = getAxisConfigInPivotChart(col, row, layout); + const axisConfig = layout.getAxisConfigInPivotChart(col, row); if (axisConfig) { + const computeAxisComponentHeight: ComputeAxisComponentHeight = + Factory.getFunction('computeAxisComponentHeight'); const axisWidth = computeAxisComponentHeight(axisConfig, table); if (typeof axisWidth === 'number') { maxHeight = isValid(maxHeight) ? Math.max(axisWidth, maxHeight) : axisWidth; diff --git a/packages/vtable/src/scenegraph/layout/update-height.ts b/packages/vtable/src/scenegraph/layout/update-height.ts index ec86864ad..89be8e15b 100644 --- a/packages/vtable/src/scenegraph/layout/update-height.ts +++ b/packages/vtable/src/scenegraph/layout/update-height.ts @@ -1,7 +1,7 @@ import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; import type { Group } from '../graphic/group'; -import { createProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; -import { createSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; +import type { CreateProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; +import type { CreateSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; import type { Scenegraph } from '../scenegraph'; import { getCellMergeInfo } from '../utils/get-cell-merge'; import { getProp } from '../utils/get-prop'; @@ -17,6 +17,7 @@ import { resizeCellGroup, getCustomCellMergeCustom } from '../group-creater/cell import type { IGraphic } from '@src/vrender'; import { getCellMergeRange } from '../../tools/merge-range'; import type { ColumnDefine } from '../../ts-types'; +import { Factory } from '../../core/factory'; export function updateRowHeight(scene: Scenegraph, row: number, detaY: number, skipTableHeightMap?: boolean) { // 更新table行高存储 @@ -139,6 +140,7 @@ export function updateCellHeight( const dataValue = scene.table.getCellOriginValue(col, row); const padding = getQuadProps(getProp('padding', style, col, row, scene.table)); + const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const newBarCell = createProgressBarCell( columnDefine, style, @@ -163,6 +165,7 @@ export function updateCellHeight( cell.removeAllChild(); const headerStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', headerStyle, col, row, scene.table)); + const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; createSparkLineCellGroup( cell, cell.parent, diff --git a/packages/vtable/src/scenegraph/layout/update-width.ts b/packages/vtable/src/scenegraph/layout/update-width.ts index cc6c521f6..81b480558 100644 --- a/packages/vtable/src/scenegraph/layout/update-width.ts +++ b/packages/vtable/src/scenegraph/layout/update-width.ts @@ -1,14 +1,15 @@ import type { IGraphic } from '@src/vrender'; import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; -import { CartesianAxis } from '../../components/axis/axis'; +import type { ICartesianAxis } from '../../components/axis/axis'; +import { Factory } from '../../core/factory'; import { getStyleTheme } from '../../core/tableHelper'; import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; import type { IProgressbarColumnBodyDefine } from '../../ts-types/list-table/define/progressbar-define'; import { CUSTOM_CONTAINER_NAME, CUSTOM_MERGE_CONTAINER_NAME, dealWithCustom } from '../component/custom'; import type { Group } from '../graphic/group'; import { updateImageCellContentWhileResize } from '../group-creater/cell-type/image-cell'; -import { createProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; -import { createSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; +import type { CreateProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; +import type { CreateSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; import { resizeCellGroup, getCustomCellMergeCustom } from '../group-creater/cell-helper'; import type { Scenegraph } from '../scenegraph'; import { getCellMergeInfo } from '../utils/get-cell-merge'; @@ -278,6 +279,7 @@ function updateCellWidth( const dataValue = scene.table.getCellOriginValue(col, row); const padding = getQuadProps(getProp('padding', style, col, row, scene.table)); + const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const newBarCell = createProgressBarCell( columnDefine, style, @@ -302,6 +304,7 @@ function updateCellWidth( cellGroup.removeAllChild(); const headerStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', headerStyle, col, row, scene.table)); + const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; createSparkLineCellGroup( cellGroup, cellGroup.parent, @@ -327,6 +330,7 @@ function updateCellWidth( const cellStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', cellStyle, col, row, scene.table)); if (axisConfig) { + const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis( axisConfig, cellGroup.attribute.width, diff --git a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts index 3f4b06281..d302c3780 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 { isEqual } from '@visactor/vutils'; import type { PivotChart } from '../../PivotChart'; -import { CartesianAxis } from '../../components/axis/axis'; +import type { ICartesianAxis } from '../../components/axis/axis'; +import { Factory } from '../../core/factory'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { Chart } from '../graphic/chart'; import type { Group } from '../graphic/group'; @@ -209,6 +210,7 @@ function updateTableAxes(containerGroup: Group, table: BaseTableAPI) { const axisConfig = table.internalProps.layoutMap.getAxisConfigInPivotChart(cell.col, cell.row); const cellStyle = table._getCellStyle(cell.col, cell.row); const padding = getQuadProps(getProp('padding', cellStyle, cell.col, cell.row, table)); + const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis(axisConfig, cell.attribute.width, cell.attribute.height, padding, table); cell.clear(); cell.appendChild(axis.component); diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index b8d869059..f144e14ab 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -72,7 +72,7 @@ import { dealWithAnimationAppear } from './animation/appear'; registerForVrender(); // VChart poptip theme -loadPoptip(); +// loadPoptip(); container.load(splitModule); container.load(textMeasureModule); // container.load(renderServiceModule); diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index f17886b97..69a9a1440 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -562,7 +562,7 @@ export interface BaseTableAPI { ) => EventListenerId; // &((type: string, listener: AnyListener) => EventListenerId); - _vDataSet: DataSet; + _vDataSet?: DataSet; /** 场景树对象 */ scenegraph: Scenegraph; /** 状态管理模块 */ diff --git a/packages/vtable/src/ts-types/table-engine.ts b/packages/vtable/src/ts-types/table-engine.ts index 8fadc8409..9dd669770 100644 --- a/packages/vtable/src/ts-types/table-engine.ts +++ b/packages/vtable/src/ts-types/table-engine.ts @@ -22,7 +22,7 @@ import type { ITitleDefine } from './pivot-table'; import type { ColumnsDefine } from './list-table'; -import type { ICellAxisOption, ITableAxisOption } from './component/axis'; +import type { ITableAxisOption } from './component/axis'; import type { IEditor } from '@visactor/vtable-editors'; import type { ITextStyleOption } from '../body-helper/style'; import type { DataSource } from '../data'; diff --git a/packages/vtable/src/ts-types/theme.ts b/packages/vtable/src/ts-types/theme.ts index 7579e0a78..d52e983f2 100644 --- a/packages/vtable/src/ts-types/theme.ts +++ b/packages/vtable/src/ts-types/theme.ts @@ -2,7 +2,6 @@ import type { ColorsDef, LineDashsDef, LineWidthsDef, LineWidthsPropertyDefine, LineDashsPropertyDefine } from '.'; import type { CheckboxStyle, ITextStyleOption, RadioStyle } from './column/style'; import type { ColorPropertyDefine, ColorsPropertyDefine } from './style-define'; -import type { ColumnIconOption } from './icon'; import type { ICellAxisOption } from './component/axis'; import type { PopTipAttributes } from '@visactor/vrender-components'; // ****** Custom Theme ******* diff --git a/packages/vtable/src/vrender.ts b/packages/vtable/src/vrender.ts index ad54c76f9..4c650f2e4 100644 --- a/packages/vtable/src/vrender.ts +++ b/packages/vtable/src/vrender.ts @@ -1,3 +1,4 @@ +import { loadPoptip } from '@visactor/vrender-components'; import '@visactor/vrender-core'; import { container, isBrowserEnv, isNodeEnv, preLoadAllModule } from '@visactor/vrender-core'; import { @@ -40,23 +41,25 @@ export function registerForVrender() { loadNodeEnv(container); } registerArc(); - registerArc3d(); - registerArea(); + // registerArc3d(); + // registerArea(); registerCircle(); - registerGlyph(); + // registerGlyph(); registerGroup(); registerImage(); registerLine(); - registerPath(); - registerPolygon(); - registerPyramid3d(); + // registerPath(); + // registerPolygon(); + // registerPyramid3d(); registerRect(); - registerRect3d(); + // registerRect3d(); registerRichtext(); - registerShadowRoot(); + // registerShadowRoot(); registerSymbol(); registerText(); - registerWrapText(); + // registerWrapText(); + + loadPoptip(); } export { Direction } from '@visactor/vrender-core'; diff --git a/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts b/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts deleted file mode 100644 index fe7c09731..000000000 --- a/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 二分靠近框架,返回数组中第一个大于等于目标值的数的索引 - * @param arr 数组 - * @param compareFn 比较函数,返回(当前值-目标值) - */ -export const binaryFuzzySearch = (arr: T[], compareFn: (value: T) => number) => { - return binaryFuzzySearchInNumberRange(0, arr.length, value => compareFn(arr[value])); -}; - -/** - * 二分靠近框架,返回数字区间中第一个大于等于目标值的数字 - * @param x1 区间上界 - * @param x2 区间下界(不包含) - * @param compareFn 比较函数,返回(当前值-目标值) - */ -export const binaryFuzzySearchInNumberRange = (x1: number, x2: number, compareFn: (value: number) => number) => { - let left = x1; - let right = x2; - while (left < right) { - const mid = Math.floor((left + right) / 2); - if (compareFn(mid) >= 0) { - right = mid; // 第一个大于等于目标值的数 - } else { - left = mid + 1; - } - } - return left; -}; diff --git a/packages/vtable/src/vutil-extension-temp/algorithm/index.ts b/packages/vtable/src/vutil-extension-temp/algorithm/index.ts deleted file mode 100644 index e10f75227..000000000 --- a/packages/vtable/src/vutil-extension-temp/algorithm/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './binary-search'; diff --git a/packages/vtable/src/vutil-extension-temp/index.ts b/packages/vtable/src/vutil-extension-temp/index.ts deleted file mode 100644 index f9d6e21f1..000000000 --- a/packages/vtable/src/vutil-extension-temp/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './transform/tick-data'; -export * from './utils'; -export * from './algorithm'; -export * from './spec'; diff --git a/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts b/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts deleted file mode 100644 index 74aec2e98..000000000 --- a/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { isArray, isBoolean, isDate, isNumber, isString, isValid } from '@visactor/vutils'; -import { isDataView, isHTMLElement } from './common'; - -/** - * 深拷贝 spec,为避免循环引用,DataView 维持原有引用 - * @param spec 原spec - */ -export function cloneDeepSpec(spec: any, excludeKeys: string[] = ['data']) { - const value = spec; - - let result; - if (!isValid(value) || typeof value !== 'object') { - return value; - } - - // 判断是不是不能深拷贝的对象 - if (isDataView(value) || isHTMLElement(value)) { - return value; - } - - const isArr = isArray(value); - const length = value.length; - // 不考虑特殊数组的额外处理 - if (isArr) { - result = new Array(length); - } - // 不考虑 buffer / arguments 类型的处理以及 prototype 的额外处理 - else if (typeof value === 'object') { - result = {}; - } - // 不建议使用作为 Boolean / Number / String 作为构造器 - else if (isBoolean(value) || isNumber(value) || isString(value)) { - result = value; - } else if (isDate(value)) { - result = new Date(+value); - } - // 不考虑 ArrayBuffer / DataView / TypedArray / map / set / regexp / symbol 类型 - else { - result = undefined; - } - - // 不考虑 map / set / TypedArray 类型的赋值 - - // 不考虑对象的 symbol 属性 - const props = isArr ? undefined : Object.keys(Object(value)); - - let index = -1; - if (result) { - while (++index < (props || value).length) { - const key = props ? props[index] : index; - const subValue = value[key]; - if (excludeKeys?.includes(key.toString())) { - result[key] = subValue; - } else { - result[key] = cloneDeepSpec(subValue, excludeKeys); - } - } - } - - return result; -} diff --git a/packages/vtable/src/vutil-extension-temp/spec/common.ts b/packages/vtable/src/vutil-extension-temp/spec/common.ts deleted file mode 100644 index a11af544c..000000000 --- a/packages/vtable/src/vutil-extension-temp/spec/common.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DataView } from '@visactor/vdataset'; - -export function isDataView(obj: any): obj is DataView { - return obj instanceof DataView; -} - -export function isHTMLElement(obj: any): obj is Element { - try { - return obj instanceof Element; - } catch { - // 跨端 plan B - const htmlElementKeys: (keyof Element)[] = [ - 'children', - 'innerHTML', - 'classList', - 'setAttribute', - 'tagName', - 'getBoundingClientRect' - ]; - const keys = Object.keys(obj); - return htmlElementKeys.every(key => keys.includes(key)); - } -} diff --git a/packages/vtable/src/vutil-extension-temp/spec/index.ts b/packages/vtable/src/vutil-extension-temp/spec/index.ts deleted file mode 100644 index 1245ec93d..000000000 --- a/packages/vtable/src/vutil-extension-temp/spec/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './clone-deep'; -export * from './common'; -export * from './merge-spec'; diff --git a/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts b/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts deleted file mode 100644 index b7d3a8433..000000000 --- a/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { isArray, isArrayLike, isObject, isPlainObject, isValid } from '@visactor/vutils'; - -function baseMerge(target: any, source: any, shallowArray = false) { - if (source) { - if (target === source) { - return; - } - if (isValid(source) && typeof source === 'object') { - // baseFor - const iterable = Object(source); - const props = []; - // keysIn - for (const key in iterable) { - props.push(key); - } - let { length } = props; - let propIndex = -1; - while (length--) { - const key = props[++propIndex]; - if ( - isValid(iterable[key]) && - typeof iterable[key] === 'object' && - !isArray(target[key]) // VChart 特有逻辑 - ) { - baseMergeDeep(target, source, key, shallowArray); - } else { - assignMergeValue(target, key, iterable[key]); - } - } - } - } -} - -// 由于目前 VChart 内部对 spec 会先执行一次深拷贝,merge 暂时不考虑 source 中有环的问题 -function baseMergeDeep(target: object, source: object, key: string, shallowArray = false) { - const objValue = target[key]; - const srcValue = source[key]; - let newValue = source[key]; - let isCommon = true; - // 不考虑 buffer / typedArray 类型 - if (isArray(srcValue)) { - if (shallowArray) { - // 依据参数对数组做浅拷贝 - newValue = []; - } else if (isArray(objValue)) { - newValue = objValue; - } else if (isArrayLike(objValue)) { - // 如果 source 为数组,则 target 的 arrayLike 对象也视作为数组处理 - newValue = new Array(objValue.length); - let index = -1; - const length = objValue.length; - while (++index < length) { - newValue[index] = objValue[index]; - } - } - } - // else if (isArray(srcValue) && shallowArray) { - // newValue = []; - // } - // 不考虑 argument 类型 - else if (isPlainObject(srcValue)) { - newValue = objValue ?? {}; - // 不考虑 prototype 的额外处理 - if (typeof objValue === 'function' || typeof objValue !== 'object') { - newValue = {}; - } - } else { - isCommon = false; - } - // 对 class 等复杂对象或者浅拷贝的 array 不做拷贝处理 - if (isCommon) { - baseMerge(newValue, srcValue, shallowArray); - } - assignMergeValue(target, key, newValue); -} - -function assignMergeValue(target: object, key: string, value: any) { - if ((value !== undefined && !eq(target[key], value)) || (value === undefined && !(key in target))) { - // 不考虑 __proto__ 的赋值处理 - target[key] = value; - } -} - -function eq(value: any, other: any) { - return value === other || (Number.isNaN(value) && Number.isNaN(other)); -} - -/* 与原生的 lodash merge 差异在于对数组是否应用最后一个 source 的结果 - * 以及对一些特殊情况的处理,比如对数组类型 padding 和对象类型的 padding 的 merge - */ -export function mergeSpec(target: any, ...sources: any[]): any { - let sourceIndex = -1; - const length = sources.length; - while (++sourceIndex < length) { - const source = sources[sourceIndex]; - baseMerge(target, source, true); - } - return target; -} - -export function mergeSpecWithFilter( - target: any, - filter: string | { type: string; index: number }, - spec: any, - forceMerge: boolean -) { - Object.keys(target).forEach(k => { - if (isObject(filter)) { - if (filter.type === k) { - if (isArray(target[k])) { - if (target[k].length >= filter.index) { - target[k][filter.index] = forceMerge ? mergeSpec({}, target[k][filter.index], spec) : spec; - } - } else { - target[k] = forceMerge ? mergeSpec({}, target[k], spec) : spec; - } - } - } else { - // filter === user id - if (isArray(target[k])) { - const index = target[k].findIndex((_s: { id: string | number }) => _s.id === filter); - if (index >= 0) { - target[k][index] = forceMerge ? mergeSpec({}, target[k][index], spec) : spec; - } - } else if (target.id === filter) { - target[k] = forceMerge ? mergeSpec({}, target[k], spec) : spec; - } - } - }); -} diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts deleted file mode 100644 index af2881fac..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts +++ /dev/null @@ -1,2 +0,0 @@ -/** 连续轴默认 tick 数量 */ -export const DEFAULT_CONTINUOUS_TICK_COUNT = 5; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts deleted file mode 100644 index 981390e38..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { LinearScale, ContinuousScale } from '@visactor/vscale'; -// eslint-disable-next-line no-duplicate-imports -import { isContinuous } from '@visactor/vscale'; -import { isFunction, isValid, last } from '@visactor/vutils'; -import { DEFAULT_CONTINUOUS_TICK_COUNT } from './config'; -import type { ICartesianTickDataOpt, ITickData, ITickDataOpt } from './interface'; -import type { ILabelItem } from './util'; -// eslint-disable-next-line no-duplicate-imports -import { convertDomainToTickData, getCartesianLabelBounds, hasOverlap, intersect } from './util'; - -/** - * 对于连续轴: - * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出LinearScale的ticks()、forceTicks()、stepTicks()结果; - * - 默认输出tickCount为10的ticks()结果。 - * - * @param scale - * @param op - * @returns - */ -export const continuousTicks = (scale: ContinuousScale, op: ITickDataOpt): ITickData[] => { - if (!isContinuous(scale.type)) { - return convertDomainToTickData(scale.domain()); - } - // if range is so small - const range = scale.range(); - const rangeSize = Math.abs(range[range.length - 1] - range[0]); - if (rangeSize < 2) { - return convertDomainToTickData([scale.domain()[0]]); - } - - const { tickCount, forceTickCount, tickStep, noDecimals = false, labelStyle } = op; - - let scaleTicks: number[]; - if (isValid(tickStep)) { - scaleTicks = (scale as LinearScale).stepTicks(tickStep); - } else if (isValid(forceTickCount)) { - scaleTicks = (scale as LinearScale).forceTicks(forceTickCount); - } else if (op.tickMode === 'd3') { - const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; - scaleTicks = (scale as LinearScale).d3Ticks(count ?? DEFAULT_CONTINUOUS_TICK_COUNT, { noDecimals }); - } else { - const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; - scaleTicks = (scale as LinearScale).ticks(count ?? DEFAULT_CONTINUOUS_TICK_COUNT, { noDecimals }); - } - - if (op.sampling) { - // 判断重叠 - if (op.coordinateType === 'cartesian' || (op.coordinateType === 'polar' && op.axisOrientType === 'radius')) { - const { labelGap = 4, labelFlush } = op as ICartesianTickDataOpt; - let items = getCartesianLabelBounds(scale, scaleTicks, op as ICartesianTickDataOpt).map( - (bounds, i) => - ({ - AABBBounds: bounds, - value: scaleTicks[i] - } as ILabelItem) - ); - while (items.length >= 3 && hasOverlap(items, labelGap)) { - items = methods.parity(items); - } - const ticks = items.map(item => item.value); - - if (ticks.length < 3 && labelFlush) { - if (ticks.length > 1) { - ticks.pop(); - } - if (last(ticks) !== last(scaleTicks)) { - ticks.push(last(scaleTicks)); - } - } - - scaleTicks = ticks; - } - } - - return convertDomainToTickData(scaleTicks); -}; - -const methods = { - parity: function (items: ILabelItem[]) { - return items.filter((item, i) => i % 2 === 0); - }, - greedy: function (items: ILabelItem[], sep: number) { - let a: ILabelItem; - return items.filter((b, i) => { - if (!i || !intersect(a.AABBBounds, b.AABBBounds, sep)) { - a = b; - return true; - } - return false; - }); - } -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts deleted file mode 100644 index 83cce6834..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts +++ /dev/null @@ -1,241 +0,0 @@ -import type { BandScale, IBaseScale } from '@visactor/vscale'; -import { isFunction, isValid, maxInArray, minInArray } from '@visactor/vutils'; -import type { ICartesianTickDataOpt, ITickData } from '../interface'; -import { convertDomainToTickData, getCartesianLabelBounds, isAxisHorizontal } from '../util'; -import { binaryFuzzySearchInNumberRange } from '../../../algorithm'; - -/** x1, x2, length */ -type OneDimensionalBounds = [number, number, number]; - -const getOneDimensionalLabelBounds = ( - scale: IBaseScale, - domain: any[], - op: ICartesianTickDataOpt, - isHorizontal: boolean -): OneDimensionalBounds[] => { - const labelBoundsList = getCartesianLabelBounds(scale, domain, op); - return labelBoundsList.map(bounds => { - if (isHorizontal) { - return [bounds.x1, bounds.x2, bounds.width()]; - } - return [bounds.y1, bounds.y2, bounds.height()]; - }); -}; - -/** 判断两个 bounds 是否有重叠情况 */ -const boundsOverlap = (prevBounds: OneDimensionalBounds, nextBounds: OneDimensionalBounds, gap = 0): boolean => { - return Math.max(prevBounds[0], nextBounds[0]) - gap / 2 <= Math.min(prevBounds[1], nextBounds[1]) + gap / 2; -}; - -/** 判断两个不相交的 bounds 相隔的距离 */ -export const boundsDistance = (prevBounds: OneDimensionalBounds, nextBounds: OneDimensionalBounds): number => { - if (prevBounds[1] < nextBounds[0]) { - return nextBounds[0] - prevBounds[1]; - } else if (nextBounds[1] < prevBounds[0]) { - return prevBounds[0] - nextBounds[1]; - } - return 0; -}; - -/** - * 对于离散轴: - * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出BandScale的ticks()、forceTicks()、stepTicks()结果; - * - 估算所有轴label的宽度(或高度,在竖轴的情况下)并存为数组domainLengthList; - * - 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡(此处用到domainLengthList和scale.range()); - * - 如果用户配置了spec.label.lastVisible,则处理右边界:强制采样最后一个tick数据,并删掉这个tick的label所覆盖的那些tick数据。 - * - * @param scale - * @param op - * @returns - */ -export const linearDiscreteTicks = (scale: BandScale, op: ICartesianTickDataOpt): ITickData[] => { - const domain = scale.domain(); - if (!domain.length) { - return []; - } - const { tickCount, forceTickCount, tickStep, labelGap = 4, axisOrientType, labelStyle } = op; - const isHorizontal = isAxisHorizontal(axisOrientType); - const range = scale.range(); - - // if range is so small - const rangeSize = scale.calculateWholeRangeSize(); - if (rangeSize < 2) { - if (op.labelLastVisible) { - return convertDomainToTickData([domain[domain.length - 1]]); - } - return convertDomainToTickData([domain[0]]); - } - - let scaleTicks; - if (isValid(tickStep)) { - scaleTicks = scale.stepTicks(tickStep); - } else if (isValid(forceTickCount)) { - scaleTicks = scale.forceTicks(forceTickCount); - } else if (isValid(tickCount)) { - const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; - scaleTicks = scale.ticks(count); - } else if (op.sampling) { - const fontSize = (op.labelStyle.fontSize ?? 12) + 2; - const rangeStart = minInArray(range); - const rangeEnd = maxInArray(range); - - if (domain.length <= rangeSize / fontSize) { - const incrementUnit = (rangeEnd - rangeStart) / domain.length; - const labelBoundsList = getOneDimensionalLabelBounds(scale, domain, op, isHorizontal); - const minBoundsLength = Math.min(...labelBoundsList.map(bounds => bounds[2])); - - const stepResult = getStep( - domain, - labelBoundsList, - labelGap, - op.labelLastVisible, - Math.floor(minBoundsLength / incrementUnit), // 给step赋上合适的初值,有效改善外层循环次数 - false - ); - - scaleTicks = (scale as BandScale).stepTicks(stepResult.step); - if (op.labelLastVisible) { - if (stepResult.delCount) { - scaleTicks = scaleTicks.slice(0, scaleTicks.length - stepResult.delCount); - } - scaleTicks.push(domain[domain.length - 1]); - } - } else { - // only check first middle last, use the max size to sampling - const tempDomain = [domain[0], domain[Math.floor(domain.length / 2)], domain[domain.length - 1]]; - const tempList = getOneDimensionalLabelBounds(scale, tempDomain, op, isHorizontal); - let maxBounds: OneDimensionalBounds = null; - tempList.forEach(current => { - if (!maxBounds) { - maxBounds = current; - return; - } - if (maxBounds[2] < current[2]) { - maxBounds = current; - } - }); - - const step = - rangeEnd - rangeStart - labelGap > 0 - ? Math.ceil((domain.length * (labelGap + maxBounds[2])) / (rangeEnd - rangeStart - labelGap)) - : domain.length - 1; - - scaleTicks = (scale as BandScale).stepTicks(step); - - if ( - op.labelLastVisible && - (!scaleTicks.length || scaleTicks[scaleTicks.length - 1] !== domain[domain.length - 1]) - ) { - if ( - scaleTicks.length && - Math.abs(scale.scale(scaleTicks[scaleTicks.length - 1]) - scale.scale(domain[domain.length - 1])) < - maxBounds[2] - ) { - scaleTicks = scaleTicks.slice(0, -1); - } - scaleTicks.push(domain[domain.length - 1]); - } - } - } else { - scaleTicks = scale.domain(); - } - - return convertDomainToTickData(scaleTicks); -}; - -/** 计算合适的step */ -const getStep = ( - domain: any[], - labelBoundsList: OneDimensionalBounds[], - labelGap: number, - labelLastVisible: boolean, - defaultStep: number, - areAllBoundsSame: boolean -) => { - let resultDelCount = 0; - let resultStep = 0; - let resultTickCount = -1; - let minDiff = Number.MAX_VALUE; - - /** 验证在当前 step 下是否会产生重叠 */ - const validateStep = (step: number) => { - let success = true; - let ptr = 0; - do { - if (ptr + step < domain.length && boundsOverlap(labelBoundsList[ptr], labelBoundsList[ptr + step], labelGap)) { - success = false; - } - ptr += step; - } while (success && ptr < domain.length); - return success; - }; - - // 通过二分来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡 - const minValidStep = binaryFuzzySearchInNumberRange(defaultStep, domain.length, step => - validateStep(step) ? 1 : -1 - ); - - // 对 step 进行微调 - let step = minValidStep; - do { - if (step > minValidStep && !areAllBoundsSame) { - if (!validateStep(step)) { - step++; - continue; - } - } - if (labelLastVisible) { - const lastIndex = domain.length - 1; - let delCount = 0; - let ptr; - if (domain.length % step > 0) { - ptr = domain.length - (domain.length % step) + step; - } else { - ptr = domain.length; - } - do { - ptr -= step; // 获取最后一个label位置 - if (ptr === lastIndex || boundsOverlap(labelBoundsList[ptr], labelBoundsList[lastIndex], labelGap)) { - delCount++; - } else { - break; - } - } while (ptr > 0); - if (ptr === lastIndex) { - // 采到的最后的一个 label 刚好是最后一项,直接退出 - resultStep = step; - resultDelCount = delCount; - break; - } else { - // 尝试获取最均匀的结果,防止倒数第二项和最后一项有大的空档 - const tickCount = Math.floor(domain.length / step) - delCount + 1; - if (tickCount < resultTickCount) { - break; - } else { - resultTickCount = tickCount; - const distance1 = boundsDistance(labelBoundsList[ptr], labelBoundsList[lastIndex]); // 倒数第2项和最后一项的距离 - const distance2 = - ptr - step >= 0 ? boundsDistance(labelBoundsList[ptr - step], labelBoundsList[ptr]) : distance1; // 倒数第3项和倒数第2项的距离 - const diff = Math.abs(distance1 - distance2); - if (diff < minDiff) { - minDiff = diff; - resultStep = step; // 记录最均匀的 step - resultDelCount = delCount; - } - if (distance1 <= distance2) { - break; - } - } - } - } else { - resultStep = step; - break; - } - step++; - } while (step <= domain.length); - - return { - step: resultStep, - delCount: resultDelCount - }; -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts deleted file mode 100644 index 361072dda..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { BandScale } from '@visactor/vscale'; -import { isFunction, isValid, maxInArray, minInArray } from '@visactor/vutils'; -import type { IPolarTickDataOpt, ITickData } from '../interface'; -import { convertDomainToTickData, getPolarAngleLabelBounds, labelOverlap } from '../util'; -import type { AABBBounds } from '@visactor/vutils'; - -/** - * 对于离散轴: - * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出BandScale的ticks()、forceTicks()、stepTicks()结果; - * - 估算所有轴label的宽高并存为数组labelBoundsList; - * - 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡(此处用到labelBoundsList和scale.range()); - * - * @param scale - * @param op - * @returns - */ -export const polarAngleAxisDiscreteTicks = (scale: BandScale, op: IPolarTickDataOpt): ITickData[] => { - const { tickCount, forceTickCount, tickStep, getRadius, labelOffset, labelGap = 0, labelStyle } = op; - const radius = getRadius?.(); - if (!radius) { - return convertDomainToTickData(scale.domain()); - } - - let scaleTicks; - if (isValid(tickStep)) { - scaleTicks = scale.stepTicks(tickStep); - } else if (isValid(forceTickCount)) { - scaleTicks = scale.forceTicks(forceTickCount); - } else if (isValid(tickCount)) { - const range = scale.range(); - const rangeSize = Math.abs(range[range.length - 1] - range[0]); - const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; - scaleTicks = scale.ticks(count); - } else if (op.sampling) { - const domain = scale.domain(); - const range = scale.range(); - - const labelBoundsList = getPolarAngleLabelBounds(scale, domain, op); - - const rangeStart = minInArray(range); - const rangeEnd = maxInArray(range); - - const axisLength = Math.abs(rangeEnd - rangeStart) * (radius + labelOffset); - const incrementUnit = axisLength / domain.length; - const { step, delCount } = getStep( - domain, - labelBoundsList, - labelGap, - Math.floor( - labelBoundsList.reduce((min, curBounds) => { - return Math.min(min, curBounds.width(), curBounds.height()); - }, Number.MAX_VALUE) / incrementUnit - ) // 给step赋上合适的初值,有效改善外层循环次数 - ); - - scaleTicks = (scale as BandScale).stepTicks(step); - scaleTicks = scaleTicks.slice(0, scaleTicks.length - delCount); - } else { - scaleTicks = scale.domain(); - } - - return convertDomainToTickData(scaleTicks); -}; - -/** 计算合适的step */ -const getStep = (domain: any[], labelBoundsList: AABBBounds[], labelGap: number, defaultStep: number) => { - let step = defaultStep; - // 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡 - do { - let success = true; - step++; - let ptr = 0; - do { - if (ptr + step < domain.length && labelOverlap(labelBoundsList[ptr], labelBoundsList[ptr + step], labelGap)) { - success = false; - } - ptr += step; - } while (success && ptr < domain.length); - if (success) { - break; - } - } while (step <= domain.length); - - let delCount = 0; - if (domain.length > 2) { - let ptr = domain.length - (domain.length % step); - if (ptr >= domain.length) { - ptr -= step; - } - // 判断首尾是否互相覆盖 - while (ptr > 0 && labelOverlap(labelBoundsList[0], labelBoundsList[ptr])) { - delCount++; - ptr -= step; - } - } - - return { - step, - delCount - }; -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts deleted file mode 100644 index 549fb07f7..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { BandScale, ContinuousScale, IBaseScale } from '@visactor/vscale'; -// eslint-disable-next-line no-duplicate-imports -import { isContinuous, isDiscrete } from '@visactor/vscale'; -import { continuousTicks } from './continuous'; -import { linearDiscreteTicks } from './discrete/linear'; -import { polarAngleAxisDiscreteTicks } from './discrete/polar-angle'; -import type { ICartesianTickDataOpt, IPolarTickDataOpt, ITickData, ITickDataOpt } from './interface'; -import { convertDomainToTickData } from './util'; - -export * from './interface'; -export { convertDomainToTickData }; - -// 总入口 -export const ticks = (scale: IBaseScale, op: ITickDataOpt): ITickData[] => { - if (isContinuous(scale.type)) { - return continuousTicks(scale as ContinuousScale, op); - } else if (isDiscrete(scale.type)) { - if (op.coordinateType === 'cartesian') { - return linearDiscreteTicks(scale as BandScale, op as ICartesianTickDataOpt); - } else if (op.coordinateType === 'polar') { - if (op.axisOrientType === 'angle') { - return polarAngleAxisDiscreteTicks(scale as BandScale, op as IPolarTickDataOpt); - } - } - } - return convertDomainToTickData(scale.domain()); -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts deleted file mode 100644 index 1c70971cd..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { ITextGraphicAttribute } from '@visactor/vrender-core'; - -export type CoordinateType = 'cartesian' | 'polar' | 'geo' | 'none'; -export type IOrientType = 'left' | 'top' | 'right' | 'bottom' | 'z'; -export type IPolarOrientType = 'radius' | 'angle'; - -export interface ITickDataOpt { - /** - * 是否进行轴采样 - */ - sampling?: boolean; - tickCount?: number | ((option: ITickCallbackOption) => number); - forceTickCount?: number; - tickStep?: number; - tickMode?: 'average' | 'd3' | string; - noDecimals?: boolean; - - coordinateType: CoordinateType; - axisOrientType: IOrientType | IPolarOrientType; - startAngle?: number; - - labelFormatter?: (value: any) => string; - labelStyle: ITextGraphicAttribute; - labelGap?: number; -} - -export interface ICartesianTickDataOpt extends ITickDataOpt { - axisOrientType: IOrientType; - labelLastVisible: boolean; - labelFlush: boolean; -} - -export interface IPolarTickDataOpt extends ITickDataOpt { - axisOrientType: IPolarOrientType; - getRadius: () => number; - labelOffset: number; - inside: boolean; -} - -export interface ITickData { - index: number; - value: number | string; - // label: string; -} - -type ITickCallbackOption = { - /** - * 坐标轴占据的画布大小。 - * 直角坐标系中为轴的宽度或高度。 - * 极坐标系中半径轴的长度。 - */ - axisLength?: number; - /** - * 轴标签的样式 - */ - labelStyle?: ITextGraphicAttribute; -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts deleted file mode 100644 index abc95029a..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts +++ /dev/null @@ -1,182 +0,0 @@ -import type { IBaseScale } from '@visactor/vscale'; -import type { IBoundsLike } from '@visactor/vutils'; -// eslint-disable-next-line no-duplicate-imports -import { AABBBounds, degreeToRadian } from '@visactor/vutils'; -import type { IGraphic, TextAlignType, TextBaselineType } from '@visactor/vrender-core'; -import { initTextMeasure } from '../../utils/text'; -import type { ICartesianTickDataOpt, IOrientType, IPolarTickDataOpt, ITickData } from './interface'; -import { getLabelPosition } from './utils/polar-label-position'; - -export const convertDomainToTickData = (domain: any[]): ITickData[] => { - const ticks = domain.map((t: number, index: number) => { - return { - index, - value: t - }; - }); - return ticks; -}; - -/** 判断两个label是否有重叠情况 */ -export const labelOverlap = (prevLabel: AABBBounds, nextLabel: AABBBounds, gap = 0): boolean => { - const prevBounds = new AABBBounds(prevLabel).expand(gap / 2); - const nextBounds = new AABBBounds(nextLabel).expand(gap / 2); - return prevBounds.intersects(nextBounds); -}; - -/** 判断两个不相交的label相隔的距离 */ -export const labelDistance = (prevLabel: AABBBounds, nextLabel: AABBBounds): [number, number] => { - let horizontal = 0; - if (prevLabel.x2 < nextLabel.x1) { - horizontal = nextLabel.x1 - prevLabel.x2; - } else if (nextLabel.x2 < prevLabel.x1) { - horizontal = prevLabel.x1 - nextLabel.x2; - } - - let vertical = 0; - if (prevLabel.y2 < nextLabel.y1) { - vertical = nextLabel.y1 - prevLabel.y2; - } else if (nextLabel.y2 < prevLabel.y1) { - vertical = prevLabel.y1 - nextLabel.y2; - } - - return [horizontal, vertical]; -}; - -export function intersect(a: IBoundsLike, b: IBoundsLike, sep: number) { - return sep > Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2); -} - -export interface ILabelItem extends Pick { - value?: T; -} - -export function hasOverlap(items: ILabelItem[], pad: number): boolean { - for (let i = 1, n = items.length, a = items[0], b; i < n; a = b, ++i) { - b = items[i]; - if (intersect(a.AABBBounds, b.AABBBounds, pad)) { - return true; - } - } - return false; -} - -export const MIN_TICK_GAP = 12; - -export const getCartesianLabelBounds = (scale: IBaseScale, domain: any[], op: ICartesianTickDataOpt): AABBBounds[] => { - const { labelStyle, axisOrientType, labelFlush, labelFormatter, startAngle = 0 } = op; - let labelAngle = labelStyle.angle ?? 0; - if (labelStyle.direction === 'vertical') { - labelAngle += degreeToRadian(90); - } - const isHorizontal = ['bottom', 'top'].includes(axisOrientType); - const isVertical = ['left', 'right'].includes(axisOrientType); - let scaleX = 1; - let scaleY = 0; - if (isHorizontal) { - // nothing to update - } else if (isVertical) { - scaleX = 0; - scaleY = 1; - } else if (startAngle) { - scaleX = Math.cos(startAngle); - scaleY = -Math.sin(startAngle); - } - - const textMeasure = initTextMeasure(labelStyle); - const labelBoundsList = domain.map((v: any, i: number) => { - const str = labelFormatter ? labelFormatter(v) : `${v}`; - - // 估算文本宽高 - const { width, height } = textMeasure.quickMeasure(str); - const textWidth = Math.max(width, MIN_TICK_GAP); - const textHeight = Math.max(height, MIN_TICK_GAP); - - // 估算文本位置 - const pos = scale.scale(v); - const baseTextX = scaleX * pos; - const baseTextY = scaleY * pos; - let textX = baseTextX; - let textY = baseTextY; - - let align: TextAlignType; - if (labelFlush && isHorizontal && i === 0) { - align = 'left'; - } else if (labelFlush && isHorizontal && i === domain.length - 1) { - align = 'right'; - } else { - align = labelStyle.textAlign ?? 'center'; - } - if (align === 'right') { - textX -= textWidth; - } else if (align === 'center') { - textX -= textWidth / 2; - } - - let baseline: TextBaselineType; - if (labelFlush && isVertical && i === 0) { - baseline = 'top'; - } else if (labelFlush && isVertical && i === domain.length - 1) { - baseline = 'bottom'; - } else { - baseline = labelStyle.textBaseline ?? 'middle'; - } - if (baseline === 'bottom') { - textY -= textHeight; - } else if (baseline === 'middle') { - textY -= textHeight / 2; - } - - // 计算 label 包围盒 - const bounds = new AABBBounds().set(textX, textY, textX + textWidth, textY + textHeight); - - if (labelAngle) { - bounds.rotate(labelAngle, baseTextX, baseTextY); - } - - return bounds; - }); - - return labelBoundsList; -}; - -export const getPolarAngleLabelBounds = (scale: IBaseScale, domain: any[], op: IPolarTickDataOpt): AABBBounds[] => { - const { labelStyle, getRadius, labelOffset, labelFormatter, inside } = op; - const radius = getRadius?.(); - const labelAngle = labelStyle.angle ?? 0; - - const textMeasure = initTextMeasure(labelStyle); - const labelBoundsList = domain.map((v: any) => { - const str = labelFormatter ? labelFormatter(v) : `${v}`; - - // 估算文本宽高 - const { width, height } = textMeasure.quickMeasure(str); - const textWidth = Math.max(width, MIN_TICK_GAP); - const textHeight = Math.max(height, MIN_TICK_GAP); - - // 估算文本位置 - const angle = scale.scale(v); - let textX = 0; - let textY = 0; - const orient = { - align: labelStyle.textAlign ?? 'center', - baseline: labelStyle.textBaseline ?? 'middle' - }; - - const { x, y } = getLabelPosition(angle, { x: 0, y: 0 }, radius, labelOffset, inside, str, labelStyle); - textX = x + (orient.align === 'right' ? -textWidth : orient.align === 'center' ? -textWidth / 2 : 0); - textY = y + (orient.baseline === 'bottom' ? -textHeight : orient.baseline === 'middle' ? -textHeight / 2 : 0); - - // 计算 label 包围盒 - const bounds = new AABBBounds() - .set(textX, textY, textX + textWidth, textY + textHeight) - .rotate(labelAngle, textX + textWidth / 2, textY + textHeight / 2); - return bounds; - }); - - return labelBoundsList; -}; - -export const isAxisHorizontal = (axisOrientType: IOrientType) => { - return (['bottom', 'top', 'z'] as IOrientType[]).includes(axisOrientType); -}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts deleted file mode 100644 index cef160c38..000000000 --- a/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { ITextGraphicAttribute } from '@visactor/vrender-core'; -import { getCircleLabelPosition, getCircleVerticalVector, getVerticalCoord } from '@visactor/vrender-components'; -import { polarToCartesian } from '@visactor/vutils'; - -export function getLabelPosition( - angle: number, - center: { x: number; y: number }, - radius: number, - labelOffset: number, - inside: boolean, - text: string | number, - style: Partial -) { - const point = polarToCartesian({ x: 0, y: 0 }, radius, angle); - const labelPoint = getVerticalCoord(point, getCircleVerticalVector(labelOffset, point, center, inside)); - const vector = getCircleVerticalVector(labelOffset || 1, labelPoint, center, inside); - return getCircleLabelPosition(labelPoint, vector, text, style); -} diff --git a/packages/vtable/src/vutil-extension-temp/utils/index.ts b/packages/vtable/src/vutil-extension-temp/utils/index.ts deleted file mode 100644 index 35641ed3a..000000000 --- a/packages/vtable/src/vutil-extension-temp/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './object'; -export * from './polar'; -export * from './text'; diff --git a/packages/vtable/src/vutil-extension-temp/utils/object.ts b/packages/vtable/src/vutil-extension-temp/utils/object.ts deleted file mode 100644 index 8798664d3..000000000 --- a/packages/vtable/src/vutil-extension-temp/utils/object.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { get, isArray, isFunction, isNil, isObject } from '@visactor/vutils'; - -/** - * 判断一个 spec 是否包含另一个 spec 片段 - * @param spec 原始 spec - * @param searchSpec 要匹配的 spec 片段 - */ -export const includeSpec = (spec: Partial, searchSpec: Partial): boolean => { - if (spec === searchSpec) { - return true; - } - if (isFunction(spec) || isFunction(searchSpec)) { - return false; - } - if (isArray(spec) && isArray(searchSpec)) { - return searchSpec.every(searchItem => spec.some(item => includeSpec(item, searchItem))); - } - if (isObject(spec) && isObject(searchSpec)) { - return Object.keys(searchSpec).every(key => includeSpec(spec[key], searchSpec[key])); - } - return false; -}; - -export const setProperty = (target: T, path: Array, value: any): T => { - if (isNil(path)) { - return target; - } - const key = path[0]; - if (isNil(key)) { - return target; - } - if (path.length === 1) { - target[key] = value; - return target; - } - if (isNil(target[key])) { - if (typeof path[1] === 'number') { - target[key] = []; - } else { - target[key] = {}; - } - } - return setProperty(target[key], path.slice(1), value); -}; - -export const getProperty = (target: any, path: Array, defaultValue?: T): T => { - if (isNil(path)) { - return undefined; - } - return get(target, path as string[], defaultValue) as T; -}; diff --git a/packages/vtable/src/vutil-extension-temp/utils/polar.ts b/packages/vtable/src/vutil-extension-temp/utils/polar.ts deleted file mode 100644 index c64ea2cf4..000000000 --- a/packages/vtable/src/vutil-extension-temp/utils/polar.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { TextAlignType, TextBaselineType } from '@visactor/vrender-core'; - -/** - * 角度标准化处理 - * @param angle 弧度角 - */ -export function normalizeAngle(angle: number): number { - while (angle < 0) { - angle += Math.PI * 2; - } - while (angle >= Math.PI * 2) { - angle -= Math.PI * 2; - } - return angle; -} - -/** - * 计算对应角度下的角度轴标签定位属性 - * @param angle 弧度角,需要注意是逆时针计算的 - * @returns - */ -export function angleLabelOrientAttribute(angle: number) { - let align: TextAlignType = 'center'; - let baseline: TextBaselineType = 'middle'; - - angle = normalizeAngle(angle); - - // left: 5/3 - 1/3; right: 2/3 - 4/3; center: 5/3 - 1/3 & 2/3 - 4/3 - if (angle >= Math.PI * (5 / 3) || angle <= Math.PI * (1 / 3)) { - align = 'left'; - } else if (angle >= Math.PI * (2 / 3) && angle <= Math.PI * (4 / 3)) { - align = 'right'; - } else { - align = 'center'; - } - - // bottom: 7/6 - 11/6; top: 1/6 - 5/6; middle: 11/6 - 1/6 & 5/6 - 7/6 - if (angle >= Math.PI * (7 / 6) && angle <= Math.PI * (11 / 6)) { - baseline = 'bottom'; - } else if (angle >= Math.PI * (1 / 6) && angle <= Math.PI * (5 / 6)) { - baseline = 'top'; - } else { - baseline = 'middle'; - } - - return { align, baseline }; -} diff --git a/packages/vtable/src/vutil-extension-temp/utils/text.ts b/packages/vtable/src/vutil-extension-temp/utils/text.ts deleted file mode 100644 index e39d0a183..000000000 --- a/packages/vtable/src/vutil-extension-temp/utils/text.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { ITextMeasureOption } from '@visactor/vutils'; -// eslint-disable-next-line no-duplicate-imports -import { TextMeasure } from '@visactor/vutils'; -import type { ITextGraphicAttribute } from '@visactor/vrender-core'; -import { getTextBounds } from '@visactor/vrender-core'; - -export const initTextMeasure = ( - textSpec?: Partial, - option?: Partial, - useNaiveCanvas?: boolean, - defaultFontParams?: Partial -): TextMeasure => { - return new TextMeasure( - { - defaultFontParams: { - fontFamily: - // eslint-disable-next-line max-len - 'PingFang SC,Helvetica Neue,Microsoft Yahei,system-ui,-apple-system,segoe ui,Roboto,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol', - fontSize: 14, - ...defaultFontParams - }, - getTextBounds: useNaiveCanvas ? undefined : getTextBounds, - specialCharSet: '-/: .,@%\'"~' + TextMeasure.ALPHABET_CHAR_SET + TextMeasure.ALPHABET_CHAR_SET.toUpperCase(), - ...(option ?? {}) - }, - textSpec - ); -};