diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cd140cd3e..539975836 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,11 +42,11 @@ jobs: NODE_OPTIONS: "--max_old_space_size=4096" run: node common/scripts/install-run-rush.js build --only tag:package - - name: Run Bugserver - working-directory: ./packages/vtable - env: - BUG_SERVER_TOKEN: ${{ secrets.BUG_SERVER_TOKEN }} - run: node ../../common/scripts/install-run-rushx.js ci + # - name: Run Bugserver + # working-directory: ./packages/vtable + # env: + # BUG_SERVER_TOKEN: ${{ secrets.BUG_SERVER_TOKEN }} + # run: node ../../common/scripts/install-run-rushx.js ci - name: Publish to npm env: diff --git a/README.md b/README.md index 1e1348eb7..93abf42e0 100644 --- a/README.md +++ b/README.md @@ -99,32 +99,28 @@ const columns =[ ]; const option = { - parentElement: document.getElementById(Table_CONTAINER_DOM_ID), + parentElement: document.getElementById(CONTAINER_ID), records:[ - { + { "230517143221027": "CA-2018-156720", "230517143221030": "JM-15580", "230517143221032": "Bagged Rubber Bands", "230517143221040": "3.024", "230517143221041": "-0.605" - }, - { + }, + { "230517143221027": "CA-2018-115427", "230517143221030": "EB-13975", "230517143221032": "GBC Binding covers", "230517143221040": "20.72", "230517143221041": "6.475" - }, - ... + }, + // ... ], columns, - widthMode:'standard' }; const tableInstance = new VTable.ListTable(option); - - - ``` ## diff --git a/README.zh-CN.md b/README.zh-CN.md index 24e3e9ac2..2cdab2147 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -97,26 +97,25 @@ const columns =[ ]; const option = { - parentElement: document.getElementById(Table_CONTAINER_DOM_ID), + parentElement: document.getElementById(CONTAINER_ID), records:[ - { + { "230517143221027": "CA-2018-156720", "230517143221030": "JM-15580", "230517143221032": "Bagged Rubber Bands", "230517143221040": "3.024", "230517143221041": "-0.605" - }, - { + }, + { "230517143221027": "CA-2018-115427", "230517143221030": "EB-13975", "230517143221032": "GBC Binding covers", "230517143221040": "20.72", "230517143221041": "6.475" - }, - ... + }, + // ... ], columns, - widthMode:'standard' }; const tableInstance = new VTable.ListTable(option); diff --git a/common/autoinstallers/lint/commitlint.config.js b/common/autoinstallers/lint/commitlint.config.js index cfade48be..0b66d7686 100644 --- a/common/autoinstallers/lint/commitlint.config.js +++ b/common/autoinstallers/lint/commitlint.config.js @@ -1,6 +1,7 @@ module.exports = { extends: ['@commitlint/config-conventional'], rules: { + 'header-min-length': [2, 'always', 16], 'not-allowed-chars': [2, 'always'] }, plugins: [ diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 306eb4ed3..70ede8c4e 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -23,7 +23,7 @@ importers: '@types/offscreencanvas': 2019.6.4 '@types/react': 16.9.49 '@types/react-dom': 16.9.8 - '@visactor/vchart': 1.0.0 + '@visactor/vchart': 1.1.0-beta.2 '@visactor/vrender': 0.11.0-alpha.3 '@visactor/vrender-components': 0.11.0-alpha.3 '@visactor/vscale': 0.9.0-alpha.2 @@ -77,7 +77,7 @@ importers: '@types/offscreencanvas': 2019.6.4 '@types/react': 16.9.49 '@types/react-dom': 16.9.8 - '@visactor/vchart': 1.0.0 + '@visactor/vchart': 1.1.0-beta.2 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.4.0 chai: 4.3.4 @@ -2704,30 +2704,30 @@ packages: resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} dev: true - /@visactor/vchart/1.0.0: - resolution: {integrity: sha512-+SoucQG3f350MpgbdXPO2AQcIeLVi+LJCWRbYL+HhPDe1NAiNzVv6jUoWxoWRB+FJKkNEhGVDyscQZ51zxJZpQ==} + /@visactor/vchart/1.1.0-beta.2: + resolution: {integrity: sha512-EYQjWJLhzYVXBg98Gg2MgcJiaNEwnmeJAIb4oLIsIXmzR6+M+os+8FlQSjrbiAeLdMA6zbCSao8xZME/lR3IOQ==} dependencies: - '@visactor/vdataset': 0.9.2-alpha.5 - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-hierarchy': 0.2.1 - '@visactor/vgrammar-projection': 0.2.1 - '@visactor/vgrammar-sankey': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 - '@visactor/vgrammar-wordcloud': 0.2.1 - '@visactor/vgrammar-wordcloud-shape': 0.2.1 + '@visactor/vdataset': 0.11.1 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-hierarchy': 0.3.2 + '@visactor/vgrammar-projection': 0.3.2 + '@visactor/vgrammar-sankey': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 + '@visactor/vgrammar-wordcloud': 0.3.2 + '@visactor/vgrammar-wordcloud-shape': 0.3.2 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vrender-components': 0.10.3 - '@visactor/vscale': 0.9.0-alpha.2 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vrender-components': 0.12.1 + '@visactor/vscale': 0.11.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vdataset/0.9.2-alpha.5: - resolution: {integrity: sha512-IS5YVv7bjIEoSYsFIXNOMmomTtS2pSTNHUw0rkPSFEnLLKTozGLCba+gmczXouRywbkeq4LMhwJGtxU3WDy2RQ==} + /@visactor/vdataset/0.11.1: + resolution: {integrity: sha512-LSlSfOkAYVGHdi7U1PMNKPOLK3ISpT24vE38L4tV8Ht8PYAciB+0m5WXEyUbQPNE7K6UC0eywHSYetPQuIOf4w==} dependencies: '@turf/flatten': 6.5.0 '@turf/helpers': 6.5.0 '@turf/rewind': 6.5.0 - '@visactor/vutils': 0.9.2-alpha.5 + '@visactor/vutils': 0.11.1 d3-dsv: 3.0.1 d3-geo: 3.1.0 d3-hexbin: 0.2.2 @@ -2743,83 +2743,74 @@ packages: topojson-client: 3.1.0 dev: true - /@visactor/vgrammar-coordinate/0.2.1: - resolution: {integrity: sha512-bqq9jpOOYu18YBsqALbkEfq5DPFXDq8YGN4/Aub32vO7MR/FGTppgVegI3D6bB5HW7T23g/N0DDoE3HuRNNj/A==} + /@visactor/vgrammar-coordinate/0.3.1: + resolution: {integrity: sha512-a0uOlHX+TQwGPAkrxOJsivo/AOmjPiI9icjfVtOJ72ctbU46Q/60Zv96PVyQ69f9ezCrQr8I72DyEGo2+95L5w==} dependencies: - '@visactor/vgrammar-util': 0.2.1 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vgrammar-util': 0.3.1 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vgrammar-hierarchy/0.2.1: - resolution: {integrity: sha512-Jj1YJNxniS0OCW0nxmyNTt4PJmEc6QAcS1LD9PGeotB68w5Vpfhe+qqczllXbmJ9ZhSp01hnxkgmwx0vmXb21A==} + /@visactor/vgrammar-hierarchy/0.3.2: + resolution: {integrity: sha512-rL/pmxs8mbYLzVRSmEXS1e2diI+Yo3dWh49vw3VmVIb2sv+9ZCQSRVMgiovHQcNb2skk7d0QviXQhBVwT3teMQ==} dependencies: - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vgrammar-projection/0.2.1: - resolution: {integrity: sha512-mlu/A5TPVvW8zH6aNqP+kaxTsMOhmErGRjpLXfmWlBbf6WGajWcCfNp8QluFXTvNWbC0sHkJT+L/7cVjN8fPlQ==} + /@visactor/vgrammar-projection/0.3.2: + resolution: {integrity: sha512-c1EiclUuxTG1jYHeaNywIb/Rog7CxPP3PUel5PMZnAN0V6of4XesDSFI2DZ4osnISQeNob6cgrqzPEBEmFAgRQ==} dependencies: - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 + '@visactor/vutils': 0.11.1 d3-geo: 1.12.1 dev: true - /@visactor/vgrammar-sankey/0.2.1: - resolution: {integrity: sha512-dTDpqoqDl+l230+CltGHKjVSjCIy18z/1y8g1v7wXrNg240qB0b7ytGS7MX4v9ED6/1alomwyci/Y/sMkwdgyw==} + /@visactor/vgrammar-sankey/0.3.2: + resolution: {integrity: sha512-4EnX1sqQA5b60kqyxWR7+uIDV6RS1soN6xRtEBB6dqLQQJt1Ihu3pPC7t3aoaTscaNDcy9EDAp5ZT/v31P8b9A==} dependencies: - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vutils': 0.9.0-alpha.2 - dev: true - - /@visactor/vgrammar-util/0.2.1: - resolution: {integrity: sha512-1WqiCNTsADk7dygQ6W/gtCXWu2GXPN0kntsR9VLIi9M0S80/JSXkGtBu3CqL5L5pVg1mLpEDuU0uFbv5105lpQ==} - dependencies: - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vgrammar-wordcloud-shape/0.2.1: - resolution: {integrity: sha512-pBLyc8IKtkmOQTobgJB+bVpagxXgDnbUfWYpUa5IrL4H3DzajECBayzlKj/i0fMzy/aCiaXiAShb4Z2dNY1IDA==} + /@visactor/vgrammar-util/0.3.1: + resolution: {integrity: sha512-MzA7arlEp21X+xn2K21Vw50Qj5oiqE+y7IrfCha88NSgpcNAQtfODb0sBUeXhzw2KT5tpxqC2xSJ33H3zR8aWQ==} dependencies: - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 - '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vscale': 0.9.0-alpha.2 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vgrammar-wordcloud/0.2.1: - resolution: {integrity: sha512-NTTT0X3LG9VwqUnuiT7YQsbCuUU5lhr5I7dyjB9iYTfj692okzdWHrtXHpNNz19/2L4lxmymboLtEWTlkrUXtg==} + /@visactor/vgrammar-wordcloud-shape/0.3.2: + resolution: {integrity: sha512-VulsTFJRmkfALrPne+xPD7UksTU9uhQn4UmsgBXWYApAy9Eiu6YsQuuMvJq5AuWL4sr0l4B+/VlpjU+KA/TQtA==} dependencies: - '@visactor/vgrammar': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vscale': 0.11.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vgrammar/0.2.1: - resolution: {integrity: sha512-rJ1qKn/BzF8hGRmwB12GAmtgtzycE8Fm9sYo9J2sX0v58VVaB5yaingP6++tktFjTG+iF+bVHTK1I3HR1nHL4Q==} + /@visactor/vgrammar-wordcloud/0.3.2: + resolution: {integrity: sha512-GdSmvpq+3WOFKR/4OqRmkKK4PDYnVSBMJUlKWNaK2ZnBPQrxObGdoVT1kWbq3TW9IQ9+GVbsml5YMitOvo3JHQ==} dependencies: - '@visactor/vgrammar-coordinate': 0.2.1 - '@visactor/vgrammar-util': 0.2.1 + '@visactor/vgrammar': 0.3.2 + '@visactor/vgrammar-util': 0.3.1 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vrender-components': 0.10.3 - '@visactor/vscale': 0.9.0-alpha.2 - '@visactor/vutils': 0.9.0-alpha.2 + '@visactor/vutils': 0.11.1 dev: true - /@visactor/vrender-components/0.10.3: - resolution: {integrity: sha512-Y/pwqOcLzqPZ9epY/Yk2581rI8d1bE3peYYz2TnWaV1O0giKz8//Rcdrc7CckpizllcMz9GrqYgRdcnBpDaMcg==} + /@visactor/vgrammar/0.3.2: + resolution: {integrity: sha512-ZBVgA5DPUSjOo8BrfyKlVJvEs1tdT7TMzZZdu26+208hIM1kWlmoBY800rQDFM21H01seXNpclMy/cI5A0KL5g==} dependencies: + '@visactor/vgrammar-coordinate': 0.3.1 + '@visactor/vgrammar-util': 0.3.1 '@visactor/vrender': 0.11.0-alpha.3 - '@visactor/vscale': 0.9.0-alpha.2 - '@visactor/vutils': 0.9.0-alpha.2 - gl-matrix: 3.4.3 + '@visactor/vrender-components': 0.12.1 + '@visactor/vscale': 0.11.2 + '@visactor/vutils': 0.11.1 dev: true /@visactor/vrender-components/0.11.0-alpha.3: @@ -2831,6 +2822,15 @@ packages: gl-matrix: 3.4.3 dev: false + /@visactor/vrender-components/0.12.1: + resolution: {integrity: sha512-N0vr5W4POZRfOsnkOZ6IeeWR6nxKfWtVtphyjX0zFzjEJ+IAnnNRuqnX6SBQzSKE0isyXwyIJN09I1+NGtJ80A==} + dependencies: + '@visactor/vrender': 0.11.0-alpha.3 + '@visactor/vscale': 0.11.2 + '@visactor/vutils': 0.11.1 + gl-matrix: 3.4.3 + dev: true + /@visactor/vrender/0.11.0-alpha.3: resolution: {integrity: sha512-rWV5ESuOxXKOfhslLs2vEFUPlpwKDB4BB8Ew7toL9HF2E+shQvTtnSAE5GT92I3UGQOl4Uj0geRIyAaHtkvxLg==} dependencies: @@ -2839,10 +2839,25 @@ packages: inversify: 6.0.1 reflect-metadata: 0.1.13 + /@visactor/vscale/0.11.2: + resolution: {integrity: sha512-50ct/lDhkT50F5oW7hnLbRYdp3m2HSkDRKXSgC7oSgPsJswz7PcLELbfjIB6gzhG2trUwMLaONe07SaC2bNIlA==} + dependencies: + '@visactor/vutils': 0.11.1 + dev: true + /@visactor/vscale/0.9.0-alpha.2: resolution: {integrity: sha512-zNQc2YeEhT86LOucDtc8tsAQV4F3zTDjHos0tlG6MEJB9sUFI4dJY93TmvAqzzu2iGD1rP1ofhDk83g3Poknnw==} dependencies: '@visactor/vutils': 0.9.0-alpha.2 + dev: false + + /@visactor/vutils/0.11.1: + resolution: {integrity: sha512-zRvkGjpAd8NPqKdh7j7Dd+RVSzFamPhbgtogcp/kqI3i6V9j6Sesj4rD/5I2rivAVYE/guDOJu0Io4waMLCj4A==} + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + eventemitter3: 4.0.7 + dev: true /@visactor/vutils/0.9.0-alpha.2: resolution: {integrity: sha512-g8zC6y4e1PKwTLK48wCeDRR24OrGoSvKQkhetjoRGu2W0deUUcC5+KMHs+eSRMo1IOiypdfi00paV7YoCBw3sA==} @@ -2850,6 +2865,7 @@ packages: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 eventemitter3: 4.0.7 + dev: false /@visactor/vutils/0.9.2-alpha.5: resolution: {integrity: sha512-EtgNA7eu7gFVTXk5f747uX/cpDPh0be56tk8gzbKsIaO6Jwld7UIe6IZ/ir/FXp+isvtStaQx1Y9QXRyWoRseQ==} diff --git a/packages/vtable/CHANGELOG.json b/packages/vtable/CHANGELOG.json index 3003ceb86..b62dc51d6 100644 --- a/packages/vtable/CHANGELOG.json +++ b/packages/vtable/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vtable", "entries": [ + { + "version": "0.9.2", + "tag": "@visactor/vtable_v0.9.2", + "date": "Wed, 26 Jul 2023 03:47:00 GMT", + "comments": { + "patch": [ + { + "comment": "refactor: chart type handle with transpose or indicator in row\n\n" + } + ] + } + }, { "version": "0.9.1", "tag": "@visactor/vtable_v0.9.1", diff --git a/packages/vtable/CHANGELOG.md b/packages/vtable/CHANGELOG.md index 8406f1f3b..95501cb83 100644 --- a/packages/vtable/CHANGELOG.md +++ b/packages/vtable/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/vtable -This log was last generated on Wed, 05 Jul 2023 06:55:19 GMT and should not be manually modified. +This log was last generated on Wed, 26 Jul 2023 03:47:00 GMT and should not be manually modified. + +## 0.9.2 +Wed, 26 Jul 2023 03:47:00 GMT + +### Patches + +- refactor: chart type handle with transpose or indicator in row + + ## 0.9.1 Wed, 05 Jul 2023 06:55:19 GMT diff --git a/packages/vtable/examples/auto-size/auto-height.ts b/packages/vtable/examples/auto-size/auto-height.ts new file mode 100644 index 000000000..d2cb8222c --- /dev/null +++ b/packages/vtable/examples/auto-size/auto-height.ts @@ -0,0 +1,107 @@ +import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; +const ListTable = VTable.ListTable; +const Table_CONTAINER_DOM_ID = 'vTable'; + +export function createTable() { + const personsDataSource: any[] = []; + for (let i = 0; i < 1000; i++) { + personsDataSource.push({ + progress: Math.ceil(20 * Math.random()), + id: i + 1, + name: 'name' + }); + } + const option: VTable.ListTableConstructorOptions = { + parentElement: document.getElementById(Table_CONTAINER_DOM_ID), + columns: [ + { + field: 'progress', + fieldFormat(rec) { + // return `已完成已完成已完成${rec.progress}%`; + let str = ''; + for (let i = 0; i < rec.progress; i++) { + str = str + '已完成'; + } + return str + rec.progress; + }, + caption: 'progress', + description: '这是一个标题的详细描述', + width: 150, + showSort: true, //显示VTable内置排序图标 + style: { + autoWrapText: true + }, + headerStyle: { + autoWrapText: true + } + }, + { + field: 'id', + caption: 'ID', + sort: (v1, v2, order) => { + if (order === 'desc') { + return v1 === v2 ? 0 : v1 > v2 ? -1 : 1; + } + return v1 === v2 ? 0 : v1 > v2 ? 1 : -1; + }, + width: 100 + }, + { + field: 'id', + fieldFormat(rec) { + return `手动换行\n这是这是第${rec.id}号`; + }, + caption: 'ID说明', + description: '这是一个ID详细描述', + sort: (v1, v2, order) => { + if (order === 'desc') { + return v1 === v2 ? 0 : v1 > v2 ? -1 : 1; + } + return v1 === v2 ? 0 : v1 > v2 ? 1 : -1; + }, + width: 150 + }, + { + caption: 'Name', + headerStyle: { + textAlign: 'center', + fontWeight: 'bold', + fontSize: 13, + fontFamily: 'sans-serif' + }, + field: 'name', + width: 150 + } + ], + showFrozenIcon: true, //显示VTable内置冻结列图标 + widthMode: 'standard', + allowFrozenColCount: 2, + defaultRowHeight: 50, + // theme: {}, + hover: { + // isShowTooltip: true, //当hover到未展示全的文本上时是否需要出现提示框 + // enableRowHighlight: true, //hover到的行,整行高亮 + // enableColumnHighlight: true, //hover到的行,整行高亮 + highlightMode: 'cross', + // enableSingalCellHighlight: true, //hover到的单元格高亮 + disableHeaderHover: true + }, + autoRowHeight: true + }; + + const instance = new ListTable(option); + + //设置表格数据 + instance.setRecords(personsDataSource, { + field: 'progress', + order: 'desc' + }); + + bindDebugTool(instance.scenegraph.stage as any, { + customGrapicKeys: ['role', '_updateTag'] + }); + + // 只为了方便控制太调试用,不要拷贝 + (window as any).tableInstance = instance; +} diff --git a/packages/vtable/examples/auto-size/auto-width.ts b/packages/vtable/examples/auto-size/auto-width.ts index bb952661e..1b23d31a1 100644 --- a/packages/vtable/examples/auto-size/auto-width.ts +++ b/packages/vtable/examples/auto-size/auto-width.ts @@ -1,4 +1,5 @@ import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; const ListTable = VTable.ListTable; const Table_CONTAINER_DOM_ID = 'vTable'; @@ -221,7 +222,7 @@ export function createTable() { const instance = new ListTable(option); - VTable.bindDebugTool(instance.scenegraph.stage as any, { + bindDebugTool(instance.scenegraph.stage as any, { customGrapicKeys: ['role', '_updateTag'] }); diff --git a/packages/vtable/examples/custom/default.ts b/packages/vtable/examples/custom/custom-layout.ts similarity index 99% rename from packages/vtable/examples/custom/default.ts rename to packages/vtable/examples/custom/custom-layout.ts index 02d5d2432..5da38bf0a 100644 --- a/packages/vtable/examples/custom/default.ts +++ b/packages/vtable/examples/custom/custom-layout.ts @@ -78,7 +78,11 @@ export function createTable() { showBounds: false, direction: 'column', alignContent: 'center', - justifyContent: 'center' + justifyContent: 'center', + background: { + fill: 'blue', + stroke: 'red' + } }); container.add(containerLeft); diff --git a/packages/vtable/examples/icon/icon-register.ts b/packages/vtable/examples/icon/icon-register.ts index 61e991584..021d51d66 100644 --- a/packages/vtable/examples/icon/icon-register.ts +++ b/packages/vtable/examples/icon/icon-register.ts @@ -2,6 +2,7 @@ import * as VTable from '../../src'; const ListTable = VTable.ListTable; const Table_CONTAINER_DOM_ID = 'vTable'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; export function createTable() { // register icon @@ -344,7 +345,13 @@ export function createTable() { title: '对象定义形式 非注册' } } - ] + ], + style: { + autoWrapText: true + }, + headerStyle: { + autoWrapText: true + } }, { field: 'id', @@ -590,7 +597,7 @@ export function createTable() { } }); - VTable.bindDebugTool(instance.scenegraph.stage as any, { + bindDebugTool(instance.scenegraph.stage as any, { customGrapicKeys: ['role', '_updateTag'] }); diff --git a/packages/vtable/examples/list/list-chart.ts b/packages/vtable/examples/list/list-chart.ts new file mode 100644 index 000000000..6389d806e --- /dev/null +++ b/packages/vtable/examples/list/list-chart.ts @@ -0,0 +1,609 @@ +/* eslint-disable */ +import * as VTable from '../../src'; +import VChart from '@visactor/vchart'; +VTable.register.chartType('vchart', VChart); +const Table_CONTAINER_DOM_ID = 'vTable'; +export function createTable() { + const columns = [ + { + field: 'personid', + caption: 'personid', + description: '这是一个标题的详细描述', + sort: true, + width: 80, + style: { + textAlign: 'left', + bgColor: '#ea9999' + } + }, + { + field: 'areaChart', + caption: 'vchart area', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'area', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + point: { + style: { + fillOpacity: 1, + stroke: '#000', + strokeWidth: 4 + }, + state: { + hover: { + fillOpacity: 0.5, + stroke: 'blue', + strokeWidth: 2 + }, + selected: { + fill: 'red' + } + } + }, + area: { + style: { + fillOpacity: 0.3, + stroke: '#000', + strokeWidth: 4 + }, + state: { + hover: { + fillOpacity: 1 + }, + selected: { + fill: 'red', + fillOpacity: 1 + } + } + }, + line: { + state: { + hover: { + stroke: 'red' + }, + selected: { + stroke: 'yellow' + } + } + }, + + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ], + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + }, + { + field: 'lineChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'line', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + line: { + state: { + hover: { + strokeWidth: 4 + }, + selected: { + stroke: 'red' + }, + hover_reverse: { + stroke: '#ddd' + } + } + }, + point: { + state: { + hover: { + fill: 'red' + }, + selected: { + fill: 'yellow' + }, + hover_reverse: { + fill: '#ddd' + } + } + }, + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ], + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + }, + { + field: 'barChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'bar', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + bar: { + state: { + hover: { + fill: 'green' + }, + selected: { + fill: 'orange' + }, + hover_reverse: { + fill: '#ccc' + } + } + } + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ] + } + }, + { + field: 'scatterChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'scatter', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type' + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ] + } + }, + { + field: 'areaChart', + caption: 'vchart area', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'area', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + point: { + style: { + fillOpacity: 1, + stroke: '#000', + strokeWidth: 4 + }, + state: { + hover: { + fillOpacity: 0.5, + stroke: 'blue', + strokeWidth: 2 + }, + selected: { + fill: 'red' + } + } + }, + area: { + style: { + fillOpacity: 0.3, + stroke: '#000', + strokeWidth: 4 + }, + state: { + hover: { + fillOpacity: 1 + }, + selected: { + fill: 'red', + fillOpacity: 1 + } + } + }, + line: { + state: { + hover: { + stroke: 'red' + }, + selected: { + stroke: 'yellow' + } + } + } + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ], + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + }, + { + field: 'lineChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'line', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + line: { + state: { + hover: { + strokeWidth: 4 + }, + selected: { + stroke: 'red' + }, + hover_reverse: { + stroke: '#ddd' + } + } + }, + point: { + state: { + hover: { + fill: 'red' + }, + selected: { + fill: 'yellow' + }, + hover_reverse: { + fill: '#ddd' + } + } + }, + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ], + legends: [ + { + visible: true, + orient: 'bottom' + } + ] + } + }, + { + field: 'barChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'bar', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type', + bar: { + state: { + hover: { + fill: 'green' + }, + selected: { + fill: 'orange' + }, + hover_reverse: { + fill: '#ccc' + } + } + } + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ] + } + }, + { + field: 'scatterChart', + caption: 'vchart line', + width: '320', + columnType: 'chart', + chartType: 'vchart', + chartSpec: { + type: 'common', + series: [ + { + type: 'scatter', + data: { + id: 'data' + }, + xField: 'x', + yField: 'y', + seriesField: 'type' + } + ], + axes: [ + { + orient: 'left', + range: { + min: 0 + } + }, + { + orient: 'bottom', + label: { + visible: true + }, + type: 'band' + } + ] + } + } + ]; + const records: any[] = []; // = generatePersonsDataSource(10); + for (let i = 1; i <= 40; i++) + records.push({ + personid: i, + areaChart: [ + { x: '0', type: 'A', y: 100 * i }, + { x: '1', type: 'A', y: '707' }, + { x: '2', type: 'A', y: '832' }, + { x: '3', type: 'A', y: '726' }, + { x: '4', type: 'A', y: '756' }, + { x: '5', type: 'A', y: '777' }, + { x: '6', type: 'A', y: '689' }, + { x: '7', type: 'A', y: '795' }, + { x: '8', type: 'A', y: '889' }, + { x: '9', type: 'A', y: '757' }, + { x: '0', type: 'B', y: '773' }, + { x: '1', type: 'B', y: '785' }, + { x: '2', type: 'B', y: '635' }, + { x: '3', type: 'B', y: '813' }, + { x: '4', type: 'B', y: '678' }, + { x: '5', type: 'B', y: 796 + 100 * i }, + { x: '6', type: 'B', y: '652' }, + { x: '7', type: 'B', y: '623' }, + { x: '8', type: 'B', y: '649' }, + { x: '9', type: 'B', y: '630' } + ], + lineChart: [ + { x: '0', type: 'A', y: 100 * i }, + { x: '1', type: 'A', y: '707' }, + { x: '2', type: 'A', y: '832' }, + { x: '3', type: 'A', y: '726' }, + { x: '4', type: 'A', y: '756' }, + { x: '5', type: 'A', y: '777' }, + { x: '6', type: 'A', y: '689' }, + { x: '7', type: 'A', y: '795' }, + { x: '8', type: 'A', y: '889' }, + { x: '9', type: 'A', y: '757' }, + { x: '0', type: 'B', y: 500 }, + { x: '1', type: 'B', y: '785' }, + { x: '2', type: 'B', y: '635' }, + { x: '3', type: 'B', y: '813' }, + { x: '4', type: 'B', y: '678' }, + { x: '5', type: 'B', y: '796' }, + { x: '6', type: 'B', y: '652' }, + { x: '7', type: 'B', y: '623' }, + { x: '8', type: 'B', y: '649' }, + { x: '9', type: 'B', y: '630' } + ], + barChart: [ + { x: '0', type: 'A', y: 100 * i }, + { x: '1', type: 'A', y: '707' }, + { x: '2', type: 'A', y: '832' }, + { x: '3', type: 'A', y: '726' }, + { x: '4', type: 'A', y: '756' }, + { x: '5', type: 'A', y: '777' }, + { x: '6', type: 'A', y: '689' }, + { x: '7', type: 'A', y: '795' }, + { x: '8', type: 'A', y: '889' }, + { x: '9', type: 'A', y: '757' }, + { x: '0', type: 'B', y: 500 }, + { x: '1', type: 'B', y: '785' }, + { x: '2', type: 'B', y: '635' }, + { x: '3', type: 'B', y: '813' }, + { x: '4', type: 'B', y: '678' }, + { x: '5', type: 'B', y: '796' }, + { x: '6', type: 'B', y: '652' }, + { x: '7', type: 'B', y: '623' }, + { x: '8', type: 'B', y: '649' }, + { x: '9', type: 'B', y: '630' } + ], + scatterChart: [ + { x: '0', type: 'A', y: 100 * i }, + { x: '1', type: 'A', y: '707' }, + { x: '2', type: 'A', y: '832' }, + { x: '3', type: 'A', y: '726' }, + { x: '4', type: 'A', y: '756' }, + { x: '5', type: 'A', y: '777' }, + { x: '6', type: 'A', y: '689' }, + { x: '7', type: 'A', y: '795' }, + { x: '8', type: 'A', y: '889' }, + { x: '9', type: 'A', y: '757' }, + { x: '0', type: 'B', y: 500 }, + { x: '1', type: 'B', y: '785' }, + { x: '2', type: 'B', y: '635' }, + { x: '3', type: 'B', y: '813' }, + { x: '4', type: 'B', y: '678' }, + { x: '5', type: 'B', y: '796' }, + { x: '6', type: 'B', y: '652' }, + { x: '7', type: 'B', y: '623' }, + { x: '8', type: 'B', y: '649' }, + { x: '9', type: 'B', y: '630' } + ] + }); + const option = { + parentElement: document.getElementById(Table_CONTAINER_DOM_ID), + records, + columns, + transpose: false, + defaultColWidth: 200, + defaultRowHeight: 200, + defaultHeaderRowHeight: 50 + }; + + const tableInstance = new VTable.ListTable(option); + (window as any).tableInstance = tableInstance; +} diff --git a/packages/vtable/examples/list/list-transpose.ts b/packages/vtable/examples/list/list-transpose.ts new file mode 100644 index 000000000..3f4e32d0a --- /dev/null +++ b/packages/vtable/examples/list/list-transpose.ts @@ -0,0 +1,82 @@ +import * as VTable from '../../src'; +const Table_CONTAINER_DOM_ID = 'vTable'; +const generatePersons = count => { + return Array.from(new Array(count)).map((_, i) => ({ + id: i + 1, + email1: `${i + 1}@xxx.com`, + name: `小明${i + 1}`, + lastName: '王', + date1: '2022年9月1日', + tel: '000-0000-0000', + sex: i % 2 === 0 ? 'boy' : 'girl', + work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', + city: 'beijing' + })); +}; + +export function createTable() { + const records = generatePersons(1000000); + const columns: VTable.ColumnsDefine = [ + { + field: 'id', + caption: 'ID', + width: 120, + sort: true + }, + { + field: 'email1', + caption: 'email', + width: 200, + sort: true + }, + { + caption: 'full name', + columns: [ + { + field: 'name', + caption: 'First Name', + width: 200 + }, + { + field: 'name', + caption: 'Last Name', + width: 200 + } + ] + }, + { + field: 'date1', + caption: 'birthday', + width: 200 + }, + { + field: 'sex', + caption: 'sex', + width: 100 + }, + { + field: 'tel', + caption: 'telephone', + width: 150 + }, + { + field: 'work', + caption: 'job', + width: 200 + }, + { + field: 'city', + caption: 'city', + width: 150 + } + ]; + const option = { + parentElement: document.getElementById(Table_CONTAINER_DOM_ID), + records, + columns, + transpose: true, + defaultColWidth: 200 + }; + const tableInstance = new VTable.ListTable(option); + (window as any).tableInstance = tableInstance; +} diff --git a/packages/vtable/examples/list/list.ts b/packages/vtable/examples/list/list.ts index 6fdb54493..99eef7102 100644 --- a/packages/vtable/examples/list/list.ts +++ b/packages/vtable/examples/list/list.ts @@ -76,5 +76,5 @@ export function createTable() { columns }; const tableInstance = new VTable.ListTable(option); - window.tableInstance = tableInstance; + (window as any).tableInstance = tableInstance; } diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index 5a43b966e..2480eb578 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -6,6 +6,10 @@ export const menus = [ path: 'list', name: 'list' }, + { + path: 'list', + name: 'list-transpose' + }, { path: 'list', name: 'list-tree' @@ -13,6 +17,10 @@ export const menus = [ { path: 'list', name: 'list-data-promise' + }, + { + path: 'list', + name: 'list-chart' } ] }, @@ -215,6 +223,10 @@ export const menus = [ { path: 'auto-size', name: 'auto-width' + }, + { + path: 'auto-size', + name: 'auto-height' } ] }, @@ -244,6 +256,15 @@ export const menus = [ } ] }, + { + menu: 'custom', + children: [ + { + path: 'custom', + name: 'custom-layout' + } + ] + }, { menu: '调试使用', children: [ diff --git a/packages/vtable/examples/style.css b/packages/vtable/examples/style.css index 424afa589..28698ee7d 100644 --- a/packages/vtable/examples/style.css +++ b/packages/vtable/examples/style.css @@ -27,7 +27,7 @@ body p { } .container .sidebar { - width: 100px; + width: 200px; /* height: 100%; */ border-right: 1px solid rgba(0, 0, 0, 0.06); } diff --git a/packages/vtable/examples/style/function.ts b/packages/vtable/examples/style/function.ts index 8c0611ce7..c02054401 100644 --- a/packages/vtable/examples/style/function.ts +++ b/packages/vtable/examples/style/function.ts @@ -1,6 +1,7 @@ import * as VTable from '../../src'; const PivotTable = VTable.PivotTable; const Table_CONTAINER_DOM_ID = 'vTable'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; function generatePivotDataSource(num, colCount) { const array = new Array(num); @@ -478,7 +479,7 @@ export function createTable() { instance.updatePivotSortState([{ dimensions: e.dimensionInfo, order }]); }); - VTable.bindDebugTool(instance.scenegraph.stage as any, { + bindDebugTool(instance.scenegraph.stage as any, { customGrapicKeys: ['role', '_updateTag'] }); diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 653f2021b..56f804064 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable", - "version": "0.9.1", + "version": "0.9.2", "description": "canvas table width high performance", "keywords": [ "grid", @@ -54,7 +54,7 @@ "@visactor/vscale": "0.9.0-alpha.2" }, "devDependencies": { - "@visactor/vchart": "1.0.0", + "@visactor/vchart": "1.1.0-beta.2", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", diff --git a/packages/vtable/site-demo/basic-functionality/auto-wrap-text.md b/packages/vtable/site-demo/basic-functionality/auto-wrap-text.md index 4e24bed7f..44438dcf7 100644 --- a/packages/vtable/site-demo/basic-functionality/auto-wrap-text.md +++ b/packages/vtable/site-demo/basic-functionality/auto-wrap-text.md @@ -4,6 +4,7 @@ group: Basic Features title: 自动换行 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/auto-wrap-text.gif order: 3-1 +link: '/guide/basic_function/auto_wrap_text' --- # 自动换行 diff --git a/packages/vtable/site-demo/basic-functionality/frozen-col.md b/packages/vtable/site-demo/basic-functionality/frozen-col.md index 30e7d50e6..a054a11a7 100644 --- a/packages/vtable/site-demo/basic-functionality/frozen-col.md +++ b/packages/vtable/site-demo/basic-functionality/frozen-col.md @@ -4,6 +4,7 @@ group: Basic Features title: 冻结列 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/frozen-col.gif order: 3-3 +link: '/guide/basic_function/frozen_column' --- # 冻结列 diff --git a/packages/vtable/site-demo/basic-functionality/sort.md b/packages/vtable/site-demo/basic-functionality/sort.md index 4a4701a0d..91ec68dd5 100644 --- a/packages/vtable/site-demo/basic-functionality/sort.md +++ b/packages/vtable/site-demo/basic-functionality/sort.md @@ -4,6 +4,7 @@ group: Basic Features title: 排序 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/sort.gif order: 3-2 +link: '/guide/basic_function/sort' --- # 排序 diff --git a/packages/vtable/site-demo/basic-functionality/width-mode-adaptive.md b/packages/vtable/site-demo/basic-functionality/width-mode-adaptive.md index b282cf8ad..3bff751bd 100644 --- a/packages/vtable/site-demo/basic-functionality/width-mode-adaptive.md +++ b/packages/vtable/site-demo/basic-functionality/width-mode-adaptive.md @@ -4,6 +4,7 @@ group: Basic Features title: 适应容器宽度 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/width-mode-adaptive.png order: 3-5 +link: '/guide/basic_function/row_height_column_width' --- # 列宽模式-适应容器宽度 diff --git a/packages/vtable/site-demo/basic-functionality/width-mode-autoWidth.md b/packages/vtable/site-demo/basic-functionality/width-mode-autoWidth.md index d28cb1277..36b026d9a 100644 --- a/packages/vtable/site-demo/basic-functionality/width-mode-autoWidth.md +++ b/packages/vtable/site-demo/basic-functionality/width-mode-autoWidth.md @@ -4,6 +4,7 @@ group: Basic Features title: 列宽适应内容 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/width-mode-autoWidth.png order: 3-6 +link: '/guide/basic_function/row_height_column_width' --- # 列宽模式-适应内容 diff --git a/packages/vtable/site-demo/cell-type/multi-type.md b/packages/vtable/site-demo/cell-type/multi-type.md index 158eed7b6..88363ff98 100644 --- a/packages/vtable/site-demo/cell-type/multi-type.md +++ b/packages/vtable/site-demo/cell-type/multi-type.md @@ -4,6 +4,7 @@ group: Cell Type title: 单元格内容类型 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/multi-type.png order: 2-1 +link: '/guide/column_type/columnType' --- # 单元格内容类型 diff --git a/packages/vtable/site-demo/cell-type/progressbar.md b/packages/vtable/site-demo/cell-type/progressbar.md index 6ab592021..c789c2766 100644 --- a/packages/vtable/site-demo/cell-type/progressbar.md +++ b/packages/vtable/site-demo/cell-type/progressbar.md @@ -4,6 +4,7 @@ group: Cell Type title: 数据条类型 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/progressbar.png order: 2-2 +link: '/guide/column_type/progressbar' --- # 数据条类型 diff --git a/packages/vtable/site-demo/component/scrollbar.md b/packages/vtable/site-demo/component/scrollbar.md index aa5c61c98..e540600e5 100644 --- a/packages/vtable/site-demo/component/scrollbar.md +++ b/packages/vtable/site-demo/component/scrollbar.md @@ -4,6 +4,7 @@ group: Component title: 滚动条 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/scrollbar.png order: 8-3 +link: '/guide/interaction_and_event/scroll' --- # 滚动条 diff --git a/packages/vtable/site-demo/custom-render/custom-cell-layout.md b/packages/vtable/site-demo/custom-render/custom-cell-layout.md index 31bba2f4f..be4cc4686 100644 --- a/packages/vtable/site-demo/custom-render/custom-cell-layout.md +++ b/packages/vtable/site-demo/custom-render/custom-cell-layout.md @@ -4,6 +4,7 @@ group: Custom title: 单元格自定义布局 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-cell-layout.png order: 7-1 +link: '/guide/custom_define/custom_layout' --- # 单元格自定义布局 diff --git a/packages/vtable/site-demo/custom-render/custom-icon.md b/packages/vtable/site-demo/custom-render/custom-icon.md index 7d5ec6ca7..2349bbcf3 100644 --- a/packages/vtable/site-demo/custom-render/custom-icon.md +++ b/packages/vtable/site-demo/custom-render/custom-icon.md @@ -4,6 +4,7 @@ group: Custom title: 自定义图标 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-icon.png order: 7-2 +link: '/guide/custom_define/custom_icon' --- # 自定义图标 diff --git a/packages/vtable/site-demo/custom-render/custom-render-global.md b/packages/vtable/site-demo/custom-render/custom-render-global.md index b442d2ca1..ba9aa6b02 100644 --- a/packages/vtable/site-demo/custom-render/custom-render-global.md +++ b/packages/vtable/site-demo/custom-render/custom-render-global.md @@ -4,6 +4,7 @@ group: Custom title: 单元格自定义内容 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-render-global.png order: 7-3 +link: '/guide/custom_define/custom_render' --- # 单元格自定义内容 diff --git a/packages/vtable/site-demo/custom-render/custom-render.md b/packages/vtable/site-demo/custom-render/custom-render.md index ad437f141..1ea3fae3a 100644 --- a/packages/vtable/site-demo/custom-render/custom-render.md +++ b/packages/vtable/site-demo/custom-render/custom-render.md @@ -4,6 +4,7 @@ group: Custom title: 单元格自定义内容 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-render.png order: 7-4 +link: '/guide/custom_define/custom_render' --- # 单元格自定义内容 diff --git a/packages/vtable/site-demo/interaction/hover-inline-cross.md b/packages/vtable/site-demo/interaction/hover-inline-cross.md index 3395ae8d4..419467943 100644 --- a/packages/vtable/site-demo/interaction/hover-inline-cross.md +++ b/packages/vtable/site-demo/interaction/hover-inline-cross.md @@ -4,6 +4,7 @@ group: Interaction title: hover行列十字高亮 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/hover-cross.png order: 4-3 +link: '/guide/interaction_and_event/hover_cell' --- # hover行列十字高亮 diff --git a/packages/vtable/site-demo/interaction/hover-inline-row.md b/packages/vtable/site-demo/interaction/hover-inline-row.md index 1a19d5e43..233548416 100644 --- a/packages/vtable/site-demo/interaction/hover-inline-row.md +++ b/packages/vtable/site-demo/interaction/hover-inline-row.md @@ -4,6 +4,7 @@ group: Interaction title: hover高亮整行 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/hover-row.png order: 4-2 +link: '/guide/interaction_and_event/hover_cell' --- # hover高亮整行 diff --git a/packages/vtable/site-demo/interaction/move-header-position.md b/packages/vtable/site-demo/interaction/move-header-position.md index d66034585..2aaf7a0c3 100644 --- a/packages/vtable/site-demo/interaction/move-header-position.md +++ b/packages/vtable/site-demo/interaction/move-header-position.md @@ -4,6 +4,7 @@ group: Interaction title: 移动表头位置 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/move-header-position.gif order: 4-5 +link: '/guide/interaction_and_event/drag_header' --- # 移动表头位置 diff --git a/packages/vtable/site-demo/interaction/resize-col-width.md b/packages/vtable/site-demo/interaction/resize-col-width.md index 9ab156343..3d1119c91 100644 --- a/packages/vtable/site-demo/interaction/resize-col-width.md +++ b/packages/vtable/site-demo/interaction/resize-col-width.md @@ -4,6 +4,7 @@ group: Interaction title: 调整列宽 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/resize-col-width.gif order: 4-4 +link: '/guide/interaction_and_event/resize_column_width' --- # 调整列宽 diff --git a/packages/vtable/site-demo/interaction/select.md b/packages/vtable/site-demo/interaction/select.md index 50088a8c5..dea35da59 100644 --- a/packages/vtable/site-demo/interaction/select.md +++ b/packages/vtable/site-demo/interaction/select.md @@ -4,6 +4,7 @@ group: Interaction title: 选择单元格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/select.png order: 4-1 +link: '/guide/interaction_and_event/select' --- # 选择单元格 diff --git a/packages/vtable/site-demo/style/style.md b/packages/vtable/site-demo/style/style.md index 1a0c17f59..ceda3748d 100644 --- a/packages/vtable/site-demo/style/style.md +++ b/packages/vtable/site-demo/style/style.md @@ -1,9 +1,10 @@ --- category: examples -group: table-type pivot-table +group: Style title: 样式 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/style.png order: 5-1 +link: '/guide/theme_and_style/style' --- # 样式 diff --git a/packages/vtable/site-demo/table-type/list-table-tree.md b/packages/vtable/site-demo/table-type/list-table-tree.md index 61dc80660..be6496522 100644 --- a/packages/vtable/site-demo/table-type/list-table-tree.md +++ b/packages/vtable/site-demo/table-type/list-table-tree.md @@ -4,6 +4,7 @@ group: table-type title: 基本表格树形展示 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/list-tree.png order: 1-2 +link: '/guide/table_type/List_table/tree_list' --- # 基本表格树形展示 diff --git a/packages/vtable/site-demo/table-type/list-table.md b/packages/vtable/site-demo/table-type/list-table.md index f882286ac..eaa2894ff 100644 --- a/packages/vtable/site-demo/table-type/list-table.md +++ b/packages/vtable/site-demo/table-type/list-table.md @@ -4,6 +4,7 @@ group: table-type title: 基本表格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/list-table.png order: 1-1 +link: '/guide/table_type/List_table/list_table_define_and_generate' --- # 基本表格 diff --git a/packages/vtable/site-demo/table-type/pivot-table-tree.md b/packages/vtable/site-demo/table-type/pivot-table-tree.md index 5721a5f07..d1d92927f 100644 --- a/packages/vtable/site-demo/table-type/pivot-table-tree.md +++ b/packages/vtable/site-demo/table-type/pivot-table-tree.md @@ -4,6 +4,7 @@ group: table-type title: 透视表格树形展示 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-tree.png order: 1-5 +link: '/guide/table_type/Pivot_table/pivot_table_tree' --- # 透视表格 diff --git a/packages/vtable/site-demo/table-type/pivot-table.md b/packages/vtable/site-demo/table-type/pivot-table.md index 3d3725151..d19f6d21f 100644 --- a/packages/vtable/site-demo/table-type/pivot-table.md +++ b/packages/vtable/site-demo/table-type/pivot-table.md @@ -4,6 +4,7 @@ group: table-type title: 透视表格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-table.png order: 1-4 +link: '/guide/table_type/Pivot_table/pivot_table_useage' --- # 透视表格 diff --git a/packages/vtable/site-demo/table-type/transpose-table.md b/packages/vtable/site-demo/table-type/transpose-table.md index d40323dd9..27848be0d 100644 --- a/packages/vtable/site-demo/table-type/transpose-table.md +++ b/packages/vtable/site-demo/table-type/transpose-table.md @@ -4,6 +4,7 @@ group: table-type title: 转置表格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/transpose.png order: 1-3 +link: '/guide/table_type/List_table/list_table_transpose' --- # 转置表格 diff --git a/packages/vtable/site-demo/theme/arco.md b/packages/vtable/site-demo/theme/arco.md index 4595dbf75..b32191c53 100644 --- a/packages/vtable/site-demo/theme/arco.md +++ b/packages/vtable/site-demo/theme/arco.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-ARCO cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/arco.png order: 6-1 +link: '/guide/theme_and_style/theme' --- # 表格主题-ARCO diff --git a/packages/vtable/site-demo/theme/bright.md b/packages/vtable/site-demo/theme/bright.md index bc6c0c2b2..0f9ff4a6f 100644 --- a/packages/vtable/site-demo/theme/bright.md +++ b/packages/vtable/site-demo/theme/bright.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-BIGTHT cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/bright.png order: 6-2 +link: '/guide/theme_and_style/theme' --- # 表格主题-BIGTHT diff --git a/packages/vtable/site-demo/theme/custom.md b/packages/vtable/site-demo/theme/custom.md index 80654dd26..41bea2da3 100644 --- a/packages/vtable/site-demo/theme/custom.md +++ b/packages/vtable/site-demo/theme/custom.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-custom cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom.png order: 6-6 +link: '/guide/theme_and_style/theme' --- # 表格主题-custom diff --git a/packages/vtable/site-demo/theme/dark.md b/packages/vtable/site-demo/theme/dark.md index 5e1645e61..931bb0d2a 100644 --- a/packages/vtable/site-demo/theme/dark.md +++ b/packages/vtable/site-demo/theme/dark.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-DARK cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/dark.png order: 6-3 +link: '/guide/theme_and_style/theme' --- # 表格主题-DARK diff --git a/packages/vtable/site-demo/theme/default.md b/packages/vtable/site-demo/theme/default.md index 7415666fe..dcc30b8e1 100644 --- a/packages/vtable/site-demo/theme/default.md +++ b/packages/vtable/site-demo/theme/default.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-DEFAULT cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/default.png order: 6-0 +link: '/guide/theme_and_style/theme' --- # 表格主题-DEFAULT diff --git a/packages/vtable/site-demo/theme/extend.md b/packages/vtable/site-demo/theme/extend.md index 366f34805..2013a923b 100644 --- a/packages/vtable/site-demo/theme/extend.md +++ b/packages/vtable/site-demo/theme/extend.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-extends cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/extend.png order: 6-5 +link: '/guide/theme_and_style/theme' --- # 表格主题-extends diff --git a/packages/vtable/site-demo/theme/register.md b/packages/vtable/site-demo/theme/register.md index 5f2fd534a..657f617cf 100644 --- a/packages/vtable/site-demo/theme/register.md +++ b/packages/vtable/site-demo/theme/register.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-register cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/register.png order: 6-7 +link: '/guide/theme_and_style/theme' --- # 表格主题-register diff --git a/packages/vtable/site-demo/theme/simplify.md b/packages/vtable/site-demo/theme/simplify.md index 2bb1f8e15..fb591f711 100644 --- a/packages/vtable/site-demo/theme/simplify.md +++ b/packages/vtable/site-demo/theme/simplify.md @@ -4,6 +4,7 @@ group: Theme title: 表格主题-SIMPLIFY cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/simplify.png order: 6-4 +link: '/guide/theme_and_style/theme' --- # 表格主题-SIMPLIFY diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 79c826ed5..17f28dd54 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -924,14 +924,27 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } let h = 0; - for (let i = startRow; i <= endRow; i++) { - h += - this.rowHeightsMap.get(i) || - (this.isColumnHeader(0, i) || this.isCornerHeader(0, i) - ? Array.isArray(this.defaultHeaderRowHeight) - ? this.defaultHeaderRowHeight[i] ?? this.internalProps.defaultRowHeight - : this.defaultHeaderRowHeight - : this.internalProps.defaultRowHeight); + // for (let i = startRow; i <= endRow; i++) { + // h += + // this.rowHeightsMap.get(i) || + // (this.isColumnHeader(0, i) || this.isCornerHeader(0, i) + // ? Array.isArray(this.defaultHeaderRowHeight) + // ? this.defaultHeaderRowHeight[i] ?? this.internalProps.defaultRowHeight + // : this.defaultHeaderRowHeight + // : this.internalProps.defaultRowHeight); + // } + // autoRowHeight || all rows in header, use accumulation + if (!this.internalProps.autoRowHeight && this.internalProps.layoutMap && endRow >= this.columnHeaderLevelCount) { + for (let i = startRow; i < this.columnHeaderLevelCount; i++) { + // part in header + h += this.getRowHeight(i); + } + // part in body + h += this.defaultRowHeight * (endRow - Math.max(this.columnHeaderLevelCount, startRow) + 1); + } else { + for (let i = startRow; i <= endRow; i++) { + h += this.getRowHeight(i); + } } if (startRow >= 0 && endRow >= 0 && h > 0) { this._rowRangeHeightsMap.set(`$${startRow}$${endRow}`, Math.round(h)); @@ -1018,17 +1031,21 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } /** * 清空含有指定row的缓存 - * @param col + * @param row */ - _clearRowRangeHeightsMap(row: number): void { - const keys = this._rowRangeHeightsMap.keys(); - for (const key of keys) { - const reg = rangeReg.exec(key); - if (reg) { - const start = Number(reg[1]); - const end = Number(reg[2]); - if (row >= start && row <= end) { - this._rowRangeHeightsMap.delete(key); + _clearRowRangeHeightsMap(row?: number): void { + if (typeof row !== 'number') { + this._rowRangeHeightsMap.clear(); + } else { + const keys = this._rowRangeHeightsMap.keys(); + for (const key of keys) { + const reg = rangeReg.exec(key); + if (reg) { + const start = Number(reg[1]); + const end = Number(reg[2]); + if (row >= start && row <= end) { + this._rowRangeHeightsMap.delete(key); + } } } } diff --git a/packages/vtable/src/event/event.ts b/packages/vtable/src/event/event.ts index 4d0131d55..4a0c53080 100644 --- a/packages/vtable/src/event/event.ts +++ b/packages/vtable/src/event/event.ts @@ -11,7 +11,7 @@ import { bindMediaClick } from './media-click'; import { bindDrillEvent, drillClick } from './drill'; import { bindSparklineHoverEvent } from './sparkline-event'; import type { BaseTableAPI } from '../ts-types/base-table'; -import { handleTextStick } from '../scenegraph/stick-text'; +import { checkHaveTextStick, handleTextStick } from '../scenegraph/stick-text'; import { bindTableGroupListener } from './listener/table-group'; import { bindScrollBarListener } from './listener/scroll-bar'; import { bindContainerDomListener } from './listener/container-dom'; @@ -74,9 +74,11 @@ export class EventManeger { }); // 处理textStick - this.table.listen(TABLE_EVENT_TYPE.SCROLL, e => { - handleTextStick(this.table); - }); + if (checkHaveTextStick(this.table)) { + this.table.listen(TABLE_EVENT_TYPE.SCROLL, e => { + handleTextStick(this.table); + }); + } // link/image/video点击 bindMediaClick(this.table); diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index b469c8669..e085fa104 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -1833,4 +1833,30 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } return undefined; } + + setChartInstance(_col: number, _row: number, chartInstance: any) { + const paths = this.getCellHeaderPaths(_col, _row); + let indicatorObj; + if (this.indicatorsAsCol) { + const indicatorKey = paths.colHeaderPaths.find(colPath => colPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicators.find(indicator => indicator.indicatorKey === indicatorKey); + } else { + const indicatorKey = paths.rowHeaderPaths.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicators.find(indicator => indicator.indicatorKey === indicatorKey); + } + indicatorObj && (indicatorObj.chartInstance = chartInstance); + } + + getChartInstance(_col: number, _row: number) { + const paths = this.getCellHeaderPaths(_col, _row); + let indicatorObj; + if (this.indicatorsAsCol) { + const indicatorKey = paths.colHeaderPaths.find(colPath => colPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicators.find(indicator => indicator.indicatorKey === indicatorKey); + } else { + const indicatorKey = paths.rowHeaderPaths.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicators.find(indicator => indicator.indicatorKey === indicatorKey); + } + return indicatorObj?.chartInstance; + } } diff --git a/packages/vtable/src/layout/pivot-layout.ts b/packages/vtable/src/layout/pivot-layout.ts index 27798c747..6d59b40c1 100644 --- a/packages/vtable/src/layout/pivot-layout.ts +++ b/packages/vtable/src/layout/pivot-layout.ts @@ -756,4 +756,30 @@ export class PivoLayoutMap implements LayoutMapAPI { } // TODO: 补充Header Move + + setChartInstance(_col: number, _row: number, chartInstance: any) { + const paths = this.getCellHeaderPaths(_col, _row); + let indicatorObj; + if (this.indicatorsAsCol) { + const indicatorKey = paths.colHeaderPaths.find(colPath => colPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicatorObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } else { + const indicatorKey = paths.rowHeaderPaths.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicatorObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } + indicatorObj && (indicatorObj.chartInstance = chartInstance); + } + + getChartInstance(_col: number, _row: number) { + const paths = this.getCellHeaderPaths(_col, _row); + let indicatorObj; + if (this.indicatorsAsCol) { + const indicatorKey = paths.colHeaderPaths.find(colPath => colPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicatorObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } else { + const indicatorKey = paths.rowHeaderPaths.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + indicatorObj = this._indicatorObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } + return indicatorObj?.chartInstance; + } } diff --git a/packages/vtable/src/layout/simple-header-layout.ts b/packages/vtable/src/layout/simple-header-layout.ts index acb80dc65..ca0ed63fa 100644 --- a/packages/vtable/src/layout/simple-header-layout.ts +++ b/packages/vtable/src/layout/simple-header-layout.ts @@ -663,4 +663,13 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { removeCellPositions }; } + setChartInstance(_col: number, _row: number, chartInstance: any) { + const columnObj = this.transpose ? this._columns[_row] : this._columns[_col]; + columnObj.chartInstance = chartInstance; + } + + getChartInstance(_col: number, _row: number) { + const columnObj = this.transpose ? this._columns[_row] : this._columns[_col]; + return columnObj.chartInstance; + } } diff --git a/packages/vtable/src/render/layout/container.ts b/packages/vtable/src/render/layout/container.ts index 51e36cce9..0376f47c2 100644 --- a/packages/vtable/src/render/layout/container.ts +++ b/packages/vtable/src/render/layout/container.ts @@ -187,6 +187,19 @@ export class Container extends BaseElement { this.updateYAlign(); const elements = []; + if (this.background && this.background.fill) { + const backgroundRect = new Rect({ + width: this.width, + height: this.height, + stroke: this.background.stroke ?? false, + fill: this.background.fill, + cornerRadius: this.background.cornerRadius ?? 0, + lineWidth: this.background.lineWidth ?? 1 + }); + backgroundRect.x += this.x + parentPos.parentX; + backgroundRect.y += this.y + parentPos.parentY; + elements.push(backgroundRect); + } if (this.showBounds) { const boundsRect = new Rect({ width: this.width, diff --git a/packages/vtable/src/scenegraph/graphic/text.ts b/packages/vtable/src/scenegraph/graphic/text.ts index c98181c6f..c89b2d76c 100644 --- a/packages/vtable/src/scenegraph/graphic/text.ts +++ b/packages/vtable/src/scenegraph/graphic/text.ts @@ -34,7 +34,6 @@ export class WrapText extends Text { // const textMeasure = graphicUtil.textMeasure; let width: number; let str: string; - const buf = 2; const attribute = this.attribute; const { maxLineWidth = textTheme.maxLineWidth, @@ -44,7 +43,7 @@ export class WrapText extends Text { fontSize = textTheme.fontSize, fontFamily = textTheme.fontFamily, stroke = textTheme.stroke, - lineHeight = attribute.lineHeight ?? (attribute.fontSize ?? textTheme.lineHeight ?? textTheme.fontSize) + buf, + lineHeight = attribute.lineHeight ?? attribute.fontSize ?? textTheme.fontSize, lineWidth = textTheme.lineWidth } = attribute; @@ -108,7 +107,7 @@ export class WrapText extends Text { textAlign = textTheme.textAlign, textBaseline = textTheme.textBaseline, fontSize = textTheme.fontSize, - lineHeight = this.attribute.lineHeight ?? this.attribute.fontSize ?? textTheme.lineHeight ?? textTheme.fontSize, + lineHeight = this.attribute.lineHeight ?? this.attribute.fontSize ?? textTheme.fontSize, ellipsis = textTheme.ellipsis, maxLineWidth, stroke = textTheme.stroke, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 2f126393f..bc6429d33 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -43,10 +43,9 @@ export function createCell( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, mayHaveIcon: boolean, - isfunctionalProps: boolean, isMerge: boolean, range: CellRange, - cellTheme?: IThemeSpec + cellTheme: IThemeSpec ): Group { let cellGroup: Group; if (type === 'text' || type === 'link') { @@ -137,7 +136,6 @@ export function createCell( textAlign, textBaseline, mayHaveIcon, - isfunctionalProps, customElementsGroup, renderDefault, cellTheme @@ -183,6 +181,7 @@ export function createCell( cellTheme ); } else if (type === 'chart') { + const chartInstance = table.internalProps.layoutMap.getChartInstance(col, row); cellGroup = createChartCellGroup( null, columnGroup, @@ -196,8 +195,9 @@ export function createCell( table.getCellValue(col, row), (define as ChartColumnDefine).chartType, (define as ChartColumnDefine).chartSpec, - (columnGroup.attribute as any).chartInstance, - table + chartInstance, + table, + cellTheme ); } else if (type === 'progressbar') { const style = table._getCellStyle(col, row) as ProgressBarStyle; @@ -218,7 +218,6 @@ export function createCell( textAlign, textBaseline, false, - true, null, true, cellTheme @@ -239,14 +238,27 @@ export function createCell( // 进度图插入到文字前,绘制在文字下 cellGroup.insertBefore(progressBarGroup, cellGroup.firstChild); } else if (type === 'sparkline') { - cellGroup = createSparkLineCellGroup(null, columnGroup, 0, y, col, row, cellWidth, cellHeight, padding, table); + cellGroup = createSparkLineCellGroup( + null, + columnGroup, + 0, + y, + col, + row, + cellWidth, + cellHeight, + padding, + table, + cellTheme + ); } return cellGroup; } export function updateCell(col: number, row: number, table: BaseTableAPI, addNew?: boolean) { - const oldCellGroup = table.scenegraph.getCell(col, row, true); + // const oldCellGroup = table.scenegraph.getCell(col, row, true); + const oldCellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); const type = table.isHeader(col, row) ? table._getHeaderLayoutMap(col, row).headerType @@ -341,8 +353,6 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew col, row, bgColorFunc, - customRender, - customLayout, cellWidth, cellHeight, oldCellGroup, @@ -419,7 +429,6 @@ function updateCellContent( textAlign, textBaseline, mayHaveIcon, - false, isMerge, range, cellTheme @@ -427,6 +436,11 @@ function updateCellContent( if (!addNew) { oldCellGroup.parent.insertAfter(newCellGroup, oldCellGroup); oldCellGroup.parent.removeChild(oldCellGroup); + + // update cache + if (table.scenegraph?.proxy.cellCache.get(col)) { + table.scenegraph?.proxy.cellCache.set(col, newCellGroup); + } } return newCellGroup; } 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 d32ee62fc..29162a7e0 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 @@ -1,10 +1,10 @@ import { Group } from '../../graphic/group'; -import { getCellTheme } from './text-cell'; import { Chart } from '../../graphic/chart'; import * as registerChartTypes from '../../../chartType'; import { getFunctionalProp } from '../../utils/get-prop'; import { isValid } from '../../../tools/util'; import type { BaseTableAPI } from '../../../ts-types/base-table'; +import type { IThemeSpec } from '@visactor/vrender'; export function createChartCellGroup( cellGroup: Group | null, columnGroup: Group, @@ -19,12 +19,12 @@ export function createChartCellGroup( chartType: any, chartSpec: any, chartInstance: any, - table: BaseTableAPI + table: BaseTableAPI, + cellTheme: IThemeSpec ) { // 获取注册的chart图表类型 const registerCharts = registerChartTypes.get(); const ClassType = registerCharts[chartType]; - const cellTheme = getCellTheme(table, col, row); const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); if (isValid(functionalPadding)) { @@ -83,34 +83,9 @@ export function createChartCellGroup( // height: height - padding[0] - padding[2], // }, }); - - // 调试使用 - // (chartGroup as Group).onBeforeAttributeUpdate = (val: any) => { - // if (val.y === 9.5) { - // console.log('ffffff------------------', val); - // } - // }; cellGroup.appendChild(chartGroup); - // 将生成的实例存到columnGroup中 已共享 - columnGroup.setAttribute('chartInstance', chartGroup.chartInstance); - - // 调试问题使用 - // if (col === 2) { - // columnGroup.AABBBounds.width(); - // chartGroup.AABBBounds.width(); - // console.log( - // 'set viewbox y1', - // Math.ceil(cellGroup.globalAABBBounds.y1 + padding[0] + table.scrollTop), - // chartGroup.globalAABBBounds.height() - // ); + // 将生成的实例存到layoutMap中 共享 + table.internalProps.layoutMap.setChartInstance(col, row, chartGroup.chartInstance); - // console.log( - // 'create chart', - // columnGroup, - // columnGroup.globalAABBBounds.y1, - // cellGroup.globalAABBBounds.y1, - // chartGroup.globalAABBBounds.y1 - // ); - // } return cellGroup; } 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 23ae030a1..453ceafa7 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 @@ -9,7 +9,6 @@ import { calcKeepAspectRatioSize } from '../../utils/keep-aspect-ratio'; import { calcStartPosition } from '../../utils/cell-pos'; import type { Scenegraph } from '../../scenegraph'; import { getProp, getFunctionalProp } from '../../utils/get-prop'; -import { getCellTheme } from './text-cell'; import { isValid } from '../../../tools/util'; import { getQuadProps } from '../../utils/padding'; @@ -29,9 +28,8 @@ export function createImageCellGroup( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, table: BaseTableAPI, - cellTheme?: IThemeSpec + cellTheme: IThemeSpec ) { - cellTheme = getCellTheme(table, col, row, cellTheme); const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); // const margin = getProp('padding', headerStyle, col, row, table); 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 c129ec09d..672e7901f 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 @@ -1,10 +1,9 @@ -import type { ILine, ISymbol } from '@visactor/vrender'; +import type { ILine, ISymbol, IThemeSpec } from '@visactor/vrender'; import { createLine, createSymbol } from '@visactor/vrender'; import { PointScale, LinearScale } from '@visactor/vscale'; import { isValid } from '../../../tools/util'; import { Group } from '../../graphic/group'; import type { CellInfo, SparklineSpec } from '../../../ts-types'; -import { getCellTheme } from './text-cell'; import type { BaseTableAPI } from '../../../ts-types/base-table'; const xScale: PointScale = new PointScale(); @@ -20,9 +19,9 @@ export function createSparkLineCellGroup( width: number, height: number, padding: number[], - table: BaseTableAPI + table: BaseTableAPI, + cellTheme: IThemeSpec ) { - const cellTheme = getCellTheme(table, col, row); // cell if (!cellGroup) { cellGroup = new Group({ 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 02e646063..4df107360 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 @@ -40,15 +40,10 @@ export function createCellGroup( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, mayHaveIcon: boolean, - isfunctionalProps: boolean, customElementsGroup: Group, renderDefault: boolean, - cellTheme?: IThemeSpec + cellTheme: IThemeSpec ): Group { - // 处理函数样式 - if (isfunctionalProps) { - cellTheme = getCellTheme(table, col, row, cellTheme); - } const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); if (isValid(functionalPadding)) { @@ -60,7 +55,7 @@ export function createCellGroup( if (cellTheme?.text?.textBaseline) { textBaseline = cellTheme?.text?.textBaseline; } - const { autoRowHeight } = table.internalProps; + // const { autoRowHeight } = table.internalProps; const autoColWidth = colWidth === 'auto'; const autoWrapText = headerStyle.autoWrapText ?? table.internalProps.autoWrapText; const lineClamp = headerStyle.lineClamp; @@ -103,7 +98,8 @@ export function createCellGroup( textStr, padding as any, autoColWidth, - autoRowHeight, + // autoRowHeight, + false, autoWrapText, typeof lineClamp === 'number' ? lineClamp : undefined, // autoColWidth ? 0 : colWidth, @@ -140,65 +136,65 @@ export function createCellGroup( return cellGroup; } -/** - * @description: 获取函数式赋值的样式,记录在cellTheme中 - * @param {BaseTableAPI} table - * @param {number} col - * @param {number} row - * @param {IThemeSpec} cellTheme - * @return {IThemeSpec | undefined} - */ -export function getCellTheme( - table: BaseTableAPI, - col: number, - row: number, - cellTheme?: IThemeSpec -): IThemeSpec | undefined { - // get column header style - const headerStyle = table._getCellStyle(col, row); - - const theme = getStyleTheme(headerStyle, table, col, row, getFunctionalProp).theme; - - for (const prop in theme.group) { - if (isValid(theme.group[prop])) { - if (!cellTheme) { - cellTheme = {}; - } - - if (!cellTheme.group) { - cellTheme.group = {}; - } - - cellTheme.group[prop] = theme.group[prop]; - } - } - - for (const prop in theme.text) { - if (isValid(theme.text[prop])) { - if (!cellTheme) { - cellTheme = {}; - } - - if (!cellTheme.text) { - cellTheme.text = {}; - } - - cellTheme.text[prop] = theme.text[prop]; - } - } - - for (const prop in theme._vtable) { - if (isValid(theme._vtable[prop])) { - if (!cellTheme) { - cellTheme = {}; - } - - if (!(cellTheme as any)._vtable) { - (cellTheme as any)._vtable = {}; - } - - (cellTheme as any)._vtable[prop] = theme._vtable[prop]; - } - } - return cellTheme; -} +// /** +// * @description: 获取函数式赋值的样式,记录在cellTheme中 +// * @param {BaseTableAPI} table +// * @param {number} col +// * @param {number} row +// * @param {IThemeSpec} cellTheme +// * @return {IThemeSpec | undefined} +// */ +// export function getCellTheme( +// table: BaseTableAPI, +// col: number, +// row: number, +// cellTheme?: IThemeSpec +// ): IThemeSpec | undefined { +// // get column header style +// const headerStyle = table._getCellStyle(col, row); + +// const theme = getStyleTheme(headerStyle, table, col, row, getFunctionalProp).theme; + +// for (const prop in theme.group) { +// if (isValid(theme.group[prop])) { +// if (!cellTheme) { +// cellTheme = {}; +// } + +// if (!cellTheme.group) { +// cellTheme.group = {}; +// } + +// cellTheme.group[prop] = theme.group[prop]; +// } +// } + +// for (const prop in theme.text) { +// if (isValid(theme.text[prop])) { +// if (!cellTheme) { +// cellTheme = {}; +// } + +// if (!cellTheme.text) { +// cellTheme.text = {}; +// } + +// cellTheme.text[prop] = theme.text[prop]; +// } +// } + +// for (const prop in theme._vtable) { +// if (isValid(theme._vtable[prop])) { +// if (!cellTheme) { +// cellTheme = {}; +// } + +// if (!(cellTheme as any)._vtable) { +// (cellTheme as any)._vtable = {}; +// } + +// (cellTheme as any)._vtable[prop] = theme._vtable[prop]; +// } +// } +// return cellTheme; +// } 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 2b8e48251..3bde50482 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 @@ -9,7 +9,6 @@ import { calcStartPosition } from '../../utils/cell-pos'; import { _adjustWidthHeight } from './image-cell'; import { getFunctionalProp, getProp } from '../../utils/get-prop'; import { isValid } from '../../../tools/util'; -import { getCellTheme } from './text-cell'; import type { BaseTableAPI } from '../../../ts-types/base-table'; const regedIcons = icons.get(); @@ -28,9 +27,8 @@ export function createVideoCellGroup( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, table: BaseTableAPI, - cellTheme?: IThemeSpec + cellTheme: IThemeSpec ) { - cellTheme = getCellTheme(table, col, row, cellTheme); const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); // const margin = getProp('padding', headerStyle, col, row, table); diff --git a/packages/vtable/src/scenegraph/group-creater/column-helper.ts b/packages/vtable/src/scenegraph/group-creater/column-helper.ts index aee1f2a87..78d7f13d8 100644 --- a/packages/vtable/src/scenegraph/group-creater/column-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/column-helper.ts @@ -49,46 +49,8 @@ export function createComplexColumn( let padding; let textAlign; let textBaseline; - let isfunctionalProps = false; /** useColumnTheme 判断是否可以使用columnTheme */ - const useColumnTheme = - ((table.isListTable() && !table.scenegraph.transpose) || - (table.isPivotTable() && (table.internalProps.layoutMap as PivotHeaderLayoutMap).indicatorsAsCol)) && - cellType === 'body'; - if (useColumnTheme) { - if (!columnGroup.childrenCount) { - // 只在首屏生效 - const { theme: columnTheme, hasFunctionPros } = getColumnGroupTheme(col, colWidth, table); - isfunctionalProps = hasFunctionPros; - // get column header style - if (columnTheme._vtable.padding) { - padding = columnTheme._vtable.padding; - } - if (columnTheme.text.textAlign) { - textAlign = columnTheme.text.textAlign; - } - if (columnTheme.text.textBaseline) { - textBaseline = columnTheme.text.textBaseline; - } - columnGroup.setTheme(columnTheme); - } else if (columnGroup.theme) { - const style = table._getCellStyle(col, table.columnHeaderLevelCount); // to be fixed - const { hasFunctionPros } = getStyleTheme(style, table, col, table.columnHeaderLevelCount, getRawProp, false); - isfunctionalProps = hasFunctionPros; - const columnTheme = columnGroup.theme.userTheme as any; - // 渐进加载时获取 - if (columnTheme._vtable.padding) { - padding = columnTheme._vtable.padding; - } - if (columnTheme.text.textAlign) { - textAlign = columnTheme.text.textAlign; - } - if (columnTheme.text.textBaseline) { - textBaseline = columnTheme.text.textBaseline; - } - } - } let bgColorFunc: Function; // 判断是否有mapping 遍历dataset中mappingRules if ((table.internalProps as PivotTableProtected)?.dataConfig?.mappingRules && cellType === 'body') { @@ -111,27 +73,24 @@ export function createComplexColumn( const row = j; const define = cellType !== 'body' ? table.getHeaderDefine(col, row) : table.getBodyColumnDefine(col, row); const mayHaveIcon = cellType !== 'body' ? true : !!define?.icon || !!define?.tree; - let cellTheme; - if (!useColumnTheme) { - const headerStyle = table._getCellStyle(col, row); - cellTheme = getStyleTheme(headerStyle, table, col, row, getProp).theme; - cellTheme.group.width = colWidth; - cellTheme.group.height = Array.isArray(defaultRowHeight) ? defaultRowHeight[row] : defaultRowHeight; - if (cellTheme._vtable.padding) { - padding = cellTheme._vtable.padding; - } - if (cellTheme.text.textAlign) { - textAlign = cellTheme.text.textAlign; - } - if (cellTheme.text.textBaseline) { - textBaseline = cellTheme.text.textBaseline; - } + const headerStyle = table._getCellStyle(col, row); + const cellTheme = getStyleTheme(headerStyle, table, col, row, getProp).theme; + cellTheme.group.width = colWidth; + cellTheme.group.height = Array.isArray(defaultRowHeight) ? defaultRowHeight[row] : defaultRowHeight; + if (cellTheme._vtable.padding) { + padding = cellTheme._vtable.padding; + } + if (cellTheme.text.textAlign) { + textAlign = cellTheme.text.textAlign; + } + if (cellTheme.text.textBaseline) { + textBaseline = cellTheme.text.textBaseline; } // margin = getProp('margin', headerStyle, col, 0, table) - let cellGroup; let cellWidth = colWidth; - let cellHeight = table.internalProps.autoRowHeight ? 0 : table.getRowHeight(row); + // let cellHeight = table.internalProps.autoRowHeight ? 0 : table.getRowHeight(row); + let cellHeight = table.getRowHeight(row); const type = (table.isHeader(col, row) ? table._getHeaderLayoutMap(col, row).headerType : table.getBodyColumnType(col, row)) || 'text'; @@ -216,7 +175,6 @@ export function createComplexColumn( textAlign, textBaseline, mayHaveIcon, - isfunctionalProps, isMerge, range, cellTheme @@ -246,7 +204,6 @@ export function createComplexColumn( textAlign, textBaseline, mayHaveIcon, - isfunctionalProps, isMerge, range, cellTheme diff --git a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts index 493f88530..bde1a5ccc 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts @@ -1,61 +1,105 @@ import type { BaseTableAPI } from '../../../ts-types/base-table'; -import type { Group } from '../../graphic/group'; -import type { WrapText } from '../../graphic/text'; -import { updateCellHeightForColumn } from '../../layout/update-height'; +import { Group } from '../../graphic/group'; +import { computeColsWidth } from '../../layout/compute-col-width'; +import { computeRowsHeight } from '../../layout/compute-row-height'; import { emptyGroup } from '../../utils/empty-group'; -import { getProp } from '../../utils/get-prop'; -import { getQuadProps } from '../../utils/padding'; import { createColGroup } from '../column'; import { createComplexColumn } from '../column-helper'; +import { dynamicSetX } from './update-position/dynamic-set-x'; +import { dynamicSetY } from './update-position/dynamic-set-y'; +import { updateAutoRow } from './update-position/update-auto-row'; export class SceneProxy { table: BaseTableAPI; - currentRow = 0; - totalRow: number; + mode: 'column' | 'row' | 'pivot' = 'column'; + rowLimit = 1000; + currentRow = 0; // 目前渐进生成的row number + totalRow: number; // 渐进完成最后一行的row number yLimitTop: number; // y > yLimitTop动态更新,否则直接修改xy yLimitBottom: number; // y < yLimitBottom动态更新,否则直接修改xy - // bottomOffset: number; - // scroll - accurateY = 0; - rowStart = 0; - rowEnd = 0; - referenceRow = 0; - - bodyTopRow: number; - bodyBottomRow: number; - bodyLeftCol: number; - bodyRightCol: number; - screenRowCount: number; - firstScreenRowLimit: number; - taskRowCount: number; - rowUpdatePos: number; - rowUpdateDirection: 'up' | 'down'; - screenTopRow: number = 0; - screenTopRowDeltaY: number; - y: number; + rowStart = 0; // 当前维护的部分第一行的row number + rowEnd = 0; // 当前维护的部分最后一行的row number + referenceRow = 0; // 当前维护的部分中间一行的row number,认为referenceRow对应当前屏幕显示范围的第一行 + bodyTopRow: number; // table body部分的第一行row number + bodyBottomRow: number; // table body部分的最后一行row number + screenRowCount: number; // 预计屏幕范围内显示的row count + firstScreenRowLimit: number; // 首屏同步加载部分最后一行的row number + taskRowCount: number; // 一次任务生成/更新的row count + rowUpdatePos: number; // 异步任务目前更新到的行的row number + rowUpdateDirection: 'up' | 'down'; // 当前行更新的方向 + screenTopRow: number = 0; // 当前屏幕范围内显示的第一行的row number + + colLimit = 1000; + bodyLeftCol: number; // table body部分的第一列col number + bodyRightCol: number; // table body部分的最后一列col number + totalCol: number; // 渐进完成最后一列的col number + colStart: number; // 当前维护的部分第一列的col number + colEnd: number; // 当前维护的部分最后一列的col number + taskColCount: number; // 一次任务生成/更新的col count + xLimitLeft: number; // x > xLimitLeft动态更新,否则直接修改xy + xLimitRight: number; // x < xLimitRight动态更新,否则直接修改xy + screenColCount: number; // 预计屏幕范围内显示的col count + firstScreenColLimit: number; // 首屏同步加载部分最后一列的col number + colUpdatePos: number; // 异步任务目前更新到的列的col number + currentCol: number; // 目前渐进生成的col number + referenceCol: number; // 当前维护的部分中间一列的col number,认为referenceCol对应当前屏幕显示范围的第一列 + screenLeftCol: number = 0; // 当前屏幕范围内显示的第一列的col number + colUpdateDirection: 'left' | 'right'; // 当前列更新方向 cellCache: Map = new Map(); // 单元格位置快速查找缓存 constructor(table: BaseTableAPI) { this.table = table; + + if (this.table.internalProps.transpose) { + this.mode = 'row'; + } else if (this.table.isPivotTable()) { + this.mode = 'pivot'; + } if (this.table.options.maintainedDataCount) { this.rowLimit = this.table.options.maintainedDataCount; } } - setParams() { + setParamsForColumn() { + this.bodyLeftCol = this.table.rowHeaderLevelCount; + this.bodyRightCol = this.table.colCount - 1; + + // compute the column info about progress creation + const totalActualBodyColCount = Math.min(this.colLimit, this.bodyRightCol - this.bodyLeftCol + 1); + this.totalCol = this.bodyLeftCol + totalActualBodyColCount - 1; // 目标渐进完成的col + this.colStart = this.bodyLeftCol; + const defaultColWidth = this.table.defaultColWidth; + this.taskColCount = Math.ceil(this.table.tableNoFrameWidth / defaultColWidth) * 1; + + // 确定动态更新限制 + const totalBodyWidth = defaultColWidth * totalActualBodyColCount; + const totalWidth = defaultColWidth * (this.bodyRightCol - this.bodyLeftCol + 1); + this.xLimitLeft = totalBodyWidth / 2; + this.xLimitRight = totalWidth - totalBodyWidth / 2; + + // 确定首屏高度范围 + const widthLimit = this.table.tableNoFrameWidth * 5; + this.screenColCount = Math.ceil(this.table.tableNoFrameWidth / defaultColWidth); + this.firstScreenColLimit = this.bodyLeftCol + Math.ceil(widthLimit / defaultColWidth); + // this.firstScreenRowLimit = this.bodyBottomRow; + + this.colUpdatePos = this.bodyRightCol; + } + + setParamsForRow() { this.bodyTopRow = this.table.columnHeaderLevelCount; this.bodyBottomRow = this.table.rowCount - 1; this.bodyLeftCol = 0; this.bodyRightCol = this.table.colCount - 1; // 计算渐进加载数量 - const totalActualBodyRowCount = Math.min(this.rowLimit, this.bodyBottomRow - this.bodyTopRow + 1); + const totalActualBodyRowCount = Math.min(this.rowLimit, this.bodyBottomRow - this.bodyTopRow + 1); // 渐进加载总row数量 this.totalRow = this.bodyTopRow + totalActualBodyRowCount - 1; // 目标渐进完成的row this.rowStart = this.bodyTopRow; const defaultRowHeight = this.table.defaultRowHeight; - this.taskRowCount = Math.ceil(this.table.tableNoFrameHeight / defaultRowHeight) * 5; + this.taskRowCount = Math.ceil(this.table.tableNoFrameHeight / defaultRowHeight) * 1; // 确定动态更新限制 const totalBodyHeight = defaultRowHeight * totalActualBodyRowCount; @@ -73,6 +117,116 @@ export class SceneProxy { this.rowUpdatePos = this.bodyBottomRow; } + async createGroupForFirstScreen( + cornerHeaderGroup: Group, + colHeaderGroup: Group, + rowHeaderGroup: Group, + bodyGroup: Group, + xOrigin: number, + yOrigin: number + ) { + // compute parameters + this.setParamsForRow(); + this.setParamsForColumn(); + + // compute colums width in first screen + this.table.internalProps._colWidthsMap.clear(); + this.table._clearColRangeWidthsMap(); + computeColsWidth(this.table, 0, Math.min(this.firstScreenColLimit, this.table.colCount - 1)); + + // compute rows height in first screen + this.table.internalProps._rowHeightsMap.clear(); + this.table._clearRowRangeHeightsMap(); + computeRowsHeight(this.table, 0, Math.min(this.firstScreenRowLimit, this.table.rowCount - 1)); + + // update colHeaderGroup rowHeaderGroup bodyGroup position + this.table.scenegraph.colHeaderGroup.setAttribute('x', this.table.getFrozenColsWidth()); + this.table.scenegraph.rowHeaderGroup.setAttribute('y', this.table.getFrozenRowsHeight()); + this.table.scenegraph.bodyGroup.setAttributes({ + x: this.table.getFrozenColsWidth(), + y: this.table.getFrozenRowsHeight() + }); + + // create cornerHeaderGroup + createColGroup( + cornerHeaderGroup, + xOrigin, + yOrigin, + 0, // colStart + this.table.rowHeaderLevelCount - 1, // colEnd + 0, // rowStart + this.table.columnHeaderLevelCount - 1, // rowEnd + 'cornerHeader', // CellType + this.table + ); + + // create colHeaderGroup + createColGroup( + colHeaderGroup, + xOrigin, + yOrigin, + this.table.rowHeaderLevelCount, // colStart + Math.min(this.firstScreenColLimit, this.table.colCount - 1), // colEnd + 0, // rowStart + this.table.columnHeaderLevelCount - 1, // rowEnd + 'columnHeader', // isHeader + this.table + ); + + // create rowHeaderGroup + createColGroup( + rowHeaderGroup, + xOrigin, + yOrigin, + 0, // colStart + this.table.rowHeaderLevelCount - 1, // colEnd + this.table.columnHeaderLevelCount, // rowStart + Math.min(this.firstScreenRowLimit, this.table.rowCount - 1), // rowEnd + 'rowHeader', // isHeader + this.table + ); + + // create bodyGroup + createColGroup( + bodyGroup, + xOrigin, + yOrigin, + this.table.rowHeaderLevelCount, // colStart + Math.min(this.firstScreenColLimit, this.table.colCount - 1), // colEnd + this.table.columnHeaderLevelCount, // rowStart + Math.min(this.firstScreenRowLimit, this.table.rowCount - 1), // rowEnd + 'body', // isHeader + this.table + ); + + // update progress information + if (!bodyGroup.firstChild) { + // 无数据 + this.currentRow = this.totalRow; + this.rowEnd = this.currentRow; + this.rowUpdatePos = this.rowEnd; + this.referenceRow = this.rowStart + Math.floor((this.rowEnd - this.rowStart) / 2); + + this.currentCol = this.totalCol; + this.colEnd = this.currentCol; + this.colUpdatePos = this.colEnd; + this.referenceCol = this.colStart + Math.floor((this.colEnd - this.colStart) / 2); + } else { + this.currentRow = (bodyGroup.firstChild as Group)?.rowNumber ?? this.totalRow; + this.rowEnd = this.currentRow; + this.rowUpdatePos = this.rowEnd; + this.referenceRow = this.rowStart + Math.floor((this.rowEnd - this.rowStart) / 2); + + this.currentCol = (bodyGroup.lastChild as Group)?.col ?? this.totalCol; + this.colEnd = this.currentCol; + this.colUpdatePos = this.colEnd; + this.referenceCol = this.colStart + Math.floor((this.colEnd - this.colStart) / 2); + + // 开始异步任务 + await this.progress(); + } + } + async createColGroupForFirstScreen( rowHeaderGroup: Group, bodyGroup: Group, @@ -80,7 +234,11 @@ export class SceneProxy { yOrigin: number, table: BaseTableAPI ) { - this.setParams(); + this.setParamsForRow(); + this.setParamsForColumn(); + + // compute row height in first screen + computeRowsHeight(table, this.table.columnHeaderLevelCount, Math.min(this.firstScreenRowLimit, table.rowCount - 1)); // 生成首屏单元格 // rowHeader @@ -142,19 +300,24 @@ export class SceneProxy { // } async progress() { return new Promise((resolve, reject) => { - setTimeout(() => { - if (this.rowUpdatePos < this.rowEnd) { + setTimeout(async () => { + if (this.colUpdatePos < this.colEnd) { + await this.updateColCellGroupsAsync(); + await this.progress(); + } else if (this.rowUpdatePos < this.rowEnd) { // console.log('progress rowUpdatePos', this.rowUpdatePos); // 先更新 - this.updateCellGroupsAsync(); - this.progress(); + await this.updateRowCellGroupsAsync(); + await this.progress(); + } else if (this.currentCol < this.totalCol) { + await this.createCol(); + await this.progress(); } else if (this.currentRow < this.totalRow) { // console.log('progress currentRow', this.currentRow); // 先更新没有需要更新的节点,在生成新节点 - this.createRow(); - this.progress(); + await this.createRow(); + await this.progress(); } - resolve(); }, 0); }); @@ -168,8 +331,20 @@ export class SceneProxy { this.createRowCellGroup(this.taskRowCount); } + async createCol() { + if (!this.taskColCount) { + return; + } + console.log('createCol', this.currentCol, this.currentCol + this.taskColCount); + this.createColGroup(this.taskRowCount); + } + createRowCellGroup(onceCount: number) { const endRow = Math.min(this.totalRow, this.currentRow + onceCount); + // compute rows height + computeRowsHeight(this.table, this.currentRow + 1, endRow); + + // create row cellGroup let maxHeight = 0; for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { const colGroup = this.table.scenegraph.getColGroup(col); @@ -189,19 +364,47 @@ export class SceneProxy { } this.table.scenegraph.bodyGroup.setAttribute('height', maxHeight); - if (this.table.internalProps.autoRowHeight) { - updateAutoRow( - this.bodyLeftCol, // colStart - this.bodyRightCol, // colEnd - this.currentRow + 1, // rowStart - endRow, // rowEnd - this.table - ); - } this.currentRow = endRow; this.rowEnd = endRow; this.rowUpdatePos = this.rowEnd; - this.referenceRow = Math.floor((endRow - this.rowStart) / 2); + this.referenceRow = this.rowStart + Math.floor((endRow - this.rowStart) / 2); + + // update container group size and border + this.table.scenegraph.updateContainer(); + this.table.scenegraph.updateBorderSizeAndPosition(); + } + + createColGroup(onceCount: number) { + // compute rows height + const endCol = Math.min(this.totalCol, this.currentCol + onceCount); + computeColsWidth(this.table, this.currentCol + 1, endCol); + + // create colGroup + const lastColumnGroup = ( + this.table.scenegraph.bodyGroup.lastChild instanceof Group + ? this.table.scenegraph.bodyGroup.lastChild + : this.table.scenegraph.bodyGroup.lastChild._prev + ) as Group; + const xOrigin = lastColumnGroup.attribute.x + lastColumnGroup.attribute.width; + const yOrigin = lastColumnGroup.attribute.y; + // create bodyGroup + createColGroup( + this.table.scenegraph.bodyGroup, + xOrigin, + yOrigin, + this.currentCol + 1, // colStart + endCol, // colEnd + this.rowStart, // rowStart + this.rowEnd, // rowEnd + 'body', // isHeader + this.table + ); + + this.currentCol = endCol; + this.colEnd = endCol; + this.colUpdatePos = this.colEnd; + this.referenceCol = this.colStart + Math.floor((endCol - this.colStart) / 2); + console.log('async', this.referenceCol, this.colStart, this.colEnd); // update container group size and border this.table.scenegraph.updateContainer(); @@ -221,204 +424,40 @@ export class SceneProxy { } } - async dynamicSetY(y: number) { - // 计算变动row range - // const screenTopRow = this.table.getRowAt(y).row; - const screenTop = (this.table as any).getTargetRowAt(y + this.table.scenegraph.colHeaderGroup.attribute.height); - if (!screenTop) { - return; - } - const screenTopRow = screenTop.row; - this.y = y; - this.screenTopRow = screenTopRow; - // this.screenTopRowDeltaY = y - this.table.getRowsHeight(this.bodyTopRow, screenTopRow - 1); - const deltaRow = screenTopRow - this.referenceRow; - if (deltaRow > 0) { - // 向下滚动,顶部cell group移到底部 - this.moveCell(deltaRow, 'up', screenTopRow); - this.updateBody(y); - // if (this.rowEnd === this.table.scenegraph.proxy.bodyBottomRow) { - // const totalHeight = this.table.getAllRowsHeight(); - // const top = totalHeight - this.table.scenegraph.height; - // this.updateBody(top); - // } else { - // this.updateBody(y); - // } - } else if (deltaRow < 0) { - // 向上滚动,底部cell group移到顶部 - this.moveCell(-deltaRow, 'down', screenTopRow); - this.updateBody(y); - // if (this.rowStart === this.bodyTopRow) { - // this.updateBody(0); - // } else { - // this.updateBody(y); - // } + async setX(x: number) { + if (x < this.xLimitLeft && this.colStart === this.bodyLeftCol) { + // 执行真实body group坐标修改 + this.table.scenegraph.setBodyAndColHeaderX(-x); + } else if (x > this.xLimitRight && this.colEnd === this.bodyRightCol) { + // 执行真实body group坐标修改 + this.table.scenegraph.setBodyAndColHeaderX(-x); } else { - // 不改变row,更新body group范围 - this.updateBody(y); + // 执行动态更新节点 + this.dynamicSetX(x); } + } - this.table.scenegraph.updateNextFrame(); + async dynamicSetY(y: number) { + dynamicSetY(y, this); + } + async dynamicSetX(x: number) { + dynamicSetX(x, this); } updateBody(y: number) { this.table.scenegraph.setBodyAndRowHeaderY(-y); } - async moveCell(count: number, direction: 'up' | 'down', screenTopRow: number) { - // 限制count范围 - if (direction === 'up' && this.rowEnd + count > this.bodyBottomRow) { - count = this.bodyBottomRow - this.rowEnd; - } else if (direction === 'down' && this.rowStart - count < this.bodyTopRow) { - count = this.rowStart - this.bodyTopRow; - } - - // 两种更新模式 - // 1. count < rowEnd - rowStart:从顶/底部移动count数量的单元格到底/顶部 - // 2. count >= rowEnd - rowStart:整体移动到目标位置 - if (count < this.rowEnd - this.rowStart) { - // 计算更新区域 - const startRow = direction === 'up' ? this.rowStart : this.rowEnd - count + 1; - const endRow = direction === 'up' ? this.rowStart + count - 1 : this.rowEnd; - // console.log('move', startRow, endRow, direction); - for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { - const colGroup = this.table.scenegraph.getColGroup(col); - for (let row = startRow; row <= endRow; row++) { - if (direction === 'up') { - const cellGroup = colGroup.firstChild as Group; - this.updateCellGroupPosition( - cellGroup, - (colGroup.lastChild as Group).row + 1, - (colGroup.lastChild as Group).attribute.y + (colGroup.lastChild as Group).attribute.height - ); - colGroup.appendChild(cellGroup); - } else { - const cellGroup = colGroup.lastChild as Group; - this.updateCellGroupPosition( - cellGroup, - (colGroup.firstChild as Group).row - 1, - (colGroup.firstChild as Group).attribute.y - cellGroup.attribute.height - ); - colGroup.insertBefore(cellGroup, colGroup.firstChild); - } - } - } - const distStartRow = direction === 'up' ? this.rowEnd + 1 : this.rowStart - count; - const distEndRow = direction === 'up' ? this.rowEnd + count : this.rowStart - 1; - - // 更新同步范围 - const syncTopRow = Math.max(this.bodyTopRow, screenTopRow - this.screenRowCount * 2); - const syncBottomRow = Math.min(this.bodyBottomRow, screenTopRow + this.screenRowCount * 3); - for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { - for (let row = syncTopRow; row <= syncBottomRow; row++) { - // const cellGroup = this.table.scenegraph.getCell(col, row); - const cellGroup = this.highPerformanceGetCell(col, row, distStartRow, distEndRow); - this.updateCellGroupContent(cellGroup); - } - } - if (this.table.internalProps.autoRowHeight) { - updateAutoRow( - this.bodyLeftCol, // colStart - this.bodyRightCol, // colEnd - syncTopRow, // rowStart - syncBottomRow, // rowEnd - this.table, - direction - ); - } - - this.rowStart = direction === 'up' ? this.rowStart + count : this.rowStart - count; - this.rowEnd = direction === 'up' ? this.rowEnd + count : this.rowEnd - count; - this.currentRow = direction === 'up' ? this.currentRow + count : this.currentRow - count; - this.totalRow = direction === 'up' ? this.totalRow + count : this.totalRow - count; - this.referenceRow = this.rowStart + Math.floor((this.rowEnd - this.rowStart) / 2); - this.rowUpdatePos = distStartRow; - this.rowUpdateDirection = direction; - console.log('move end proxy', this.rowStart, this.rowEnd); - console.log( - 'move end cell', - (this.table as any).scenegraph.bodyGroup.firstChild.firstChild.row, - (this.table as any).scenegraph.bodyGroup.firstChild.lastChild.row - ); - - this.table.scenegraph.stage.render(); - await this.progress(); - } else { - const distStartRow = direction === 'up' ? this.rowStart + count : this.rowStart - count; - const distEndRow = direction === 'up' ? this.rowEnd + count : this.rowEnd - count; - const distStartRowY = this.table.getRowsHeight(this.bodyTopRow, distStartRow - 1); - for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { - const colGroup = this.table.scenegraph.getColGroup(col); - colGroup.forEachChildren((cellGroup: Group, index) => { - // 这里使用colGroup变量而不是for this.rowStart to this.rowEndthis.rowEnd是因为在更新内可能出现row号码重复的情况 - this.updateCellGroupPosition( - cellGroup, - direction === 'up' ? cellGroup.row + count : cellGroup.row - count, - index === 0 // row === this.rowStart - ? distStartRowY - : (cellGroup._prev as Group).attribute.y + (cellGroup._prev as Group).attribute.height - ); - }); - } - - // 更新同步范围 - let syncTopRow; - let syncBottomRow; - if (this.table.internalProps.autoRowHeight) { - syncTopRow = distStartRow; - syncBottomRow = distEndRow; - } else { - syncTopRow = Math.max(this.bodyTopRow, screenTopRow - this.screenRowCount * 2); - syncBottomRow = Math.min(this.bodyBottomRow, screenTopRow + this.screenRowCount * 3); - } - console.log('更新同步范围', syncTopRow, syncBottomRow); - for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { - for (let row = syncTopRow; row <= syncBottomRow; row++) { - // const cellGroup = this.table.scenegraph.getCell(col, row); - const cellGroup = this.highPerformanceGetCell(col, row, distStartRow, distEndRow); - this.updateCellGroupContent(cellGroup); - } - } - console.log('updateAutoRow', distEndRow > this.bodyBottomRow - (this.rowEnd - this.rowStart + 1) ? 'down' : 'up'); - - if (this.table.internalProps.autoRowHeight) { - updateAutoRow( - this.bodyLeftCol, // colStart - this.bodyRightCol, // colEnd - syncTopRow, // rowStart - syncBottomRow, // rowEnd - this.table, - distEndRow > this.bodyBottomRow - (this.rowEnd - this.rowStart + 1) ? 'down' : 'up' // 跳转到底部时,从下向上对齐 - ); - } - - this.rowStart = distStartRow; - this.rowEnd = distEndRow; - this.currentRow = direction === 'up' ? this.currentRow + count : this.currentRow - count; - this.totalRow = direction === 'up' ? this.totalRow + count : this.totalRow - count; - this.referenceRow = this.rowStart + Math.floor((this.rowEnd - this.rowStart) / 2); - this.rowUpdatePos = this.rowStart; - this.rowUpdateDirection = distEndRow > this.bodyBottomRow - (this.rowEnd - this.rowStart + 1) ? 'down' : 'up'; - console.log('move total end proxy', this.rowStart, this.rowEnd); - console.log( - 'move total end cell', - (this.table as any).scenegraph.bodyGroup.firstChild.firstChild.row, - (this.table as any).scenegraph.bodyGroup.firstChild.lastChild.row - ); - - if (!this.table.internalProps.autoRowHeight) { - await this.progress(); - } - } - } - - async updateCellGroupsAsync() { + async updateRowCellGroupsAsync() { this.updateCellGroups(this.taskRowCount); } updateCellGroups(count: number) { const distRow = Math.min(this.bodyBottomRow, this.rowUpdatePos + count); - console.log('updateCellGroups', this.rowUpdatePos, distRow); + // console.log('updateCellGroups', this.rowUpdatePos, distRow); + if (this.table.internalProps.autoRowHeight) { + computeRowsHeight(this.table, this.rowUpdatePos, distRow); + } for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { for (let row = this.rowUpdatePos; row <= distRow; row++) { // const cellGroup = this.table.scenegraph.getCell(col, row); @@ -441,6 +480,36 @@ export class SceneProxy { this.rowUpdatePos = distRow + 1; } + async updateColCellGroupsAsync() { + this.updateColGroups(this.taskRowCount); + } + + updateColGroups(count: number) { + const distCol = Math.min(this.bodyRightCol, this.colUpdatePos + count); + // console.log('updateCellGroups', this.colUpdatePos, distCol); + for (let col = this.colUpdatePos; col <= distCol; col++) { + const colGroup = this.table.scenegraph.getColGroup(col); + if (colGroup) { + // colGroup.forEachChildren((cellGroup: Group) => { + // this.updateCellGroupContent(cellGroup); + // }); + // for (let row = (colGroup.firstChild as Group).row; row <= (colGroup.lastChild as Group).row; row++) { + // const cellGroup = this.highPerformanceGetCell(colGroup.col, row); + // this.updateCellGroupContent(cellGroup); + // } + let cellGroup = colGroup.firstChild; + while (cellGroup) { + // this.updateCellGroupContent(cellGroup as Group); + // cellGroup = cellGroup._next; + const newCellGroup = this.updateCellGroupContent(cellGroup as Group); + cellGroup = newCellGroup._next; + } + colGroup.needUpdate = false; + } + } + this.colUpdatePos = distCol + 1; + } + updateCellGroupPosition(cellGroup: Group, newRow: number, y: number) { // 更新位置&row cellGroup.row = newRow; @@ -451,10 +520,10 @@ export class SceneProxy { updateCellGroupContent(cellGroup: Group) { if (!cellGroup.needUpdate) { - return; + return cellGroup; } - this.table.scenegraph.updateCellContent(cellGroup.col, cellGroup.row); + const newCellGroup = this.table.scenegraph.updateCellContent(cellGroup.col, cellGroup.row); // 更新内容 // const textMark = cellGroup.firstChild as WrapText; // const autoWrapText = Array.isArray(textMark.attribute.text); @@ -469,6 +538,7 @@ export class SceneProxy { // textMark.setAttribute('text', text); cellGroup.needUpdate = false; + return newCellGroup || cellGroup; } async sortCell() { @@ -491,6 +561,9 @@ export class SceneProxy { syncBottomRow = Math.min(this.bodyBottomRow, this.screenTopRow + this.screenRowCount * 3); } console.log('sort更新同步范围', syncTopRow, syncBottomRow); + if (this.table.internalProps.autoRowHeight) { + computeRowsHeight(this.table, syncTopRow, syncBottomRow); + } for (let col = this.bodyLeftCol; col <= this.bodyRightCol; col++) { for (let row = syncTopRow; row <= syncBottomRow; row++) { // const cellGroup = this.table.scenegraph.getCell(col, row); @@ -530,103 +603,40 @@ export class SceneProxy { } } - highPerformanceGetCell(col: number, row: number, rowStart: number = this.rowStart, rowEnd: number = this.rowEnd) { + highPerformanceGetCell( + col: number, + row: number, + rowStart: number = this.rowStart, + rowEnd: number = this.rowEnd, + getShadow?: boolean + ) { if (row < rowStart || row > rowEnd) { return emptyGroup; } + if (row < this.rowStart || row > this.rowEnd || col < this.colStart || col > this.colEnd) { + return emptyGroup; + } if (this.cellCache.get(col)) { const cacheCellGoup = this.cellCache.get(col); if ((cacheCellGoup._next || cacheCellGoup._prev) && Math.abs(cacheCellGoup.row - row) < row) { // 由缓存单元格向前后查找要快于从头查找 let cellGroup = getCellByCache(cacheCellGoup, row); if (!cellGroup) { - cellGroup = this.table.scenegraph.getCell(col, row); + cellGroup = this.table.scenegraph.getCell(col, row, getShadow); } cellGroup.row && this.cellCache.set(col, cellGroup); return cellGroup; } - const cellGroup = this.table.scenegraph.getCell(col, row); + const cellGroup = this.table.scenegraph.getCell(col, row, getShadow); cellGroup.row && this.cellCache.set(col, cellGroup); return cellGroup; } - const cellGroup = this.table.scenegraph.getCell(col, row); + const cellGroup = this.table.scenegraph.getCell(col, row, getShadow); cellGroup.row && this.cellCache.set(col, cellGroup); return cellGroup; } } -function updateAutoRow( - colStart: number, - colEnd: number, - rowStart: number, - rowEnd: number, - table: BaseTableAPI, - direction: 'up' | 'down' = 'up' -) { - // 获取行高 - for (let row = rowStart; row <= rowEnd; row++) { - let maxRowHeight = 0; - for (let col = colStart; col <= colEnd; col++) { - const cellGroup = table.scenegraph.getCell(col, row); - if (!cellGroup.row) { - continue; - } - // const contentHeight = cellGroup.getContentHeight(); - const text = (cellGroup.getChildByName('text') as WrapText) || cellGroup.getChildByName('content'); - const headerStyle = table._getCellStyle(col, row); - const padding = getQuadProps(getProp('padding', headerStyle, col, row, table)); - const height = text.AABBBounds.height() + (padding[0] + padding[2]); - maxRowHeight = Math.max(maxRowHeight, height); - (cellGroup as any).needUpdateForAutoRowHeight = false; - } - // updateRowHeight(table.scenegraph, row, table.getRowHeight(row) - maxRowHeight); - for (let col = colStart; col <= colEnd; col++) { - const cellGroup = table.scenegraph.getCell(col, row); - updateCellHeightForColumn(table.scenegraph, cellGroup, col, row, maxRowHeight, 0, false); - } - - table.setRowHeight(row, maxRowHeight, true); - } - - // 更新y位置 - if (direction === 'up') { - for (let col = colStart; col <= colEnd; col++) { - for (let row = rowStart; row <= rowEnd; row++) { - const cellGroup = table.scenegraph.getCell(col, row); - if (!cellGroup.row) { - continue; - } - let y; - if (cellGroup._prev) { - y = ((cellGroup._prev as Group)?.attribute.y ?? 0) + ((cellGroup._prev as Group)?.attribute.height ?? 0); - } else { - // 估计位置 - y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row - 1); - } - cellGroup.setAttribute('y', y); - } - } - } else { - for (let col = colStart; col <= colEnd; col++) { - for (let row = rowEnd; row >= rowStart; row--) { - const cellGroup = table.scenegraph.getCell(col, row); - if (!cellGroup.row) { - continue; - } - let y; - if (cellGroup._next) { - y = ((cellGroup._next as Group)?.attribute.y ?? 0) - (cellGroup.attribute.height ?? 0); - } else { - // 估计位置 - y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row) - (cellGroup.attribute.height ?? 0); - console.log('估计位置', table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row)); - } - cellGroup.setAttribute('y', y); - } - } - } -} - function getCellByCache(cacheCellGroup: Group, row: number): Group | null { if (!cacheCellGroup) { return null; diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts new file mode 100644 index 000000000..caf402584 --- /dev/null +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts @@ -0,0 +1,184 @@ +import type { BaseTableAPI } from '../../../../ts-types/base-table'; +import type { Group } from '../../../graphic/group'; +import { computeColsWidth } from '../../../layout/compute-col-width'; +import type { SceneProxy } from '../proxy'; + +export async function dynamicSetX(x: number, proxy: SceneProxy) { + const screenLeft = (proxy.table as BaseTableAPI).getTargetColAt( + x + proxy.table.scenegraph.rowHeaderGroup.attribute.width + ); + if (!screenLeft) { + return; + } + + proxy.screenLeftCol = screenLeft.col; + const deltaCol = proxy.screenLeftCol - proxy.referenceCol; + + if (deltaCol > 0) { + // 向右滚动,左部column group移到右部 + proxy.table.scenegraph.setBodyAndColHeaderX(-x); + await moveColumn(deltaCol, 'left', proxy.screenLeftCol, proxy); + } else if (deltaCol < 0) { + // 向左滚动,右部cell group移到左部 + proxy.table.scenegraph.setBodyAndColHeaderX(-x); + await moveColumn(-deltaCol, 'right', proxy.screenLeftCol, proxy); + } else { + // 不改变row,更新body group范围 + proxy.table.scenegraph.setBodyAndColHeaderX(-x); + } + + proxy.table.scenegraph.updateNextFrame(); +} + +async function moveColumn(count: number, direction: 'left' | 'right', screenLeftCol: number, proxy: SceneProxy) { + // 限制count范围 + if (direction === 'left' && proxy.colEnd + count > proxy.bodyRightCol) { + count = proxy.bodyRightCol - proxy.colEnd; + } else if (direction === 'right' && proxy.colStart - count < proxy.bodyLeftCol) { + count = proxy.colStart - proxy.bodyLeftCol; + } + + const bodyGroup = proxy.table.scenegraph.bodyGroup; + + // 两种更新模式 + // 1. count < colEnd - colStart:从顶/底部移动count数量的单元格到底/顶部 + // 2. count >= colEnd - colStart:整体移动到目标位置 + if (count < proxy.colEnd - proxy.colStart) { + // 计算更新区域 + const startCol = direction === 'left' ? proxy.colStart : proxy.colEnd - count + 1; + const endCol = direction === 'left' ? proxy.colStart + count - 1 : proxy.colEnd; + const distStartCol = direction === 'left' ? proxy.colEnd + 1 : proxy.colStart - count; + const distEndCol = direction === 'left' ? proxy.colEnd + count : proxy.colStart - 1; + // update column width + computeColsWidth(proxy.table, distStartCol, distEndCol); + + // console.log('move', startCol, endCol, direction); + for (let col = startCol; col <= endCol; col++) { + if (direction === 'left') { + const colGroup = bodyGroup.firstChild as Group; + updateColGroupPosition( + colGroup, + (bodyGroup.lastChild as Group).col + 1, + (bodyGroup.lastChild as Group).attribute.x + (bodyGroup.lastChild as Group).attribute.width + ); + bodyGroup.appendChild(colGroup); + } else { + const colGroup = bodyGroup.lastChild as Group; + updateColGroupPosition( + colGroup, + (bodyGroup.firstChild as Group).col - 1, + (bodyGroup.firstChild as Group).attribute.x - proxy.table.getColWidth((bodyGroup.firstChild as Group).col - 1) + ); + bodyGroup.insertBefore(colGroup, bodyGroup.firstChild); + } + } + + // 更新同步范围 + const syncLeftCol = Math.max(proxy.bodyLeftCol, screenLeftCol - proxy.screenColCount * 1); + const syncRightCol = Math.min(proxy.bodyRightCol, screenLeftCol + proxy.screenColCount * 2); + for (let col = syncLeftCol; col <= syncRightCol; col++) { + const colGroup = proxy.table.scenegraph.getColGroup(col); + updateColGroupContent(colGroup, proxy); + } + + proxy.colStart = direction === 'left' ? proxy.colStart + count : proxy.colStart - count; + proxy.colEnd = direction === 'left' ? proxy.colEnd + count : proxy.colEnd - count; + proxy.currentCol = direction === 'left' ? proxy.currentCol + count : proxy.currentCol - count; + proxy.totalCol = direction === 'left' ? proxy.totalCol + count : proxy.totalCol - count; + proxy.referenceCol = proxy.colStart + Math.floor((proxy.colEnd - proxy.colStart) / 2); + proxy.colUpdatePos = distStartCol; + proxy.colUpdateDirection = direction; + // console.log('col move end proxy', proxy.colStart, proxy.colEnd); + // console.log( + // 'col move end cell col', + // (proxy.table as any).scenegraph.bodyGroup.firstChild.col, + // (proxy.table as any).scenegraph.bodyGroup.lastChild.col + // ); + // console.log('sync', proxy.referenceCol, proxy.colStart, proxy.colEnd); + + proxy.table.scenegraph.stage.render(); + + // 开始异步任务 + await proxy.progress(); + } else { + const distStartCol = direction === 'left' ? proxy.colStart + count : proxy.colStart - count; + const distEndCol = direction === 'left' ? proxy.colEnd + count : proxy.colEnd - count; + + // update column width + computeColsWidth(proxy.table, distStartCol, distEndCol); + const distStartColY = proxy.table.getColsWidth(proxy.bodyLeftCol, distStartCol - 1); + console.log('distStartColY', proxy.bodyLeftCol, distStartCol - 1, distStartColY); + + bodyGroup.forEachChildren((colGroup: Group, index) => { + if (colGroup.type === 'group') { + updateColGroupPosition( + colGroup, + direction === 'left' ? colGroup.col + count : colGroup.col - count, + // (bodyGroup.lastChild as Group).attribute.x + (bodyGroup.lastChild as Group).attribute.width + index === 0 // row === proxy.rowStart + ? distStartColY + : (colGroup._prev as Group).attribute.x + proxy.table.getColWidth((colGroup._prev as Group).col) + ); + } + }); + + // 更新同步范围 + const syncLeftCol = Math.max(proxy.bodyLeftCol, screenLeftCol - proxy.screenRowCount * 1); + const syncRightCol = Math.min(proxy.bodyRightCol, screenLeftCol + proxy.screenRowCount * 2); + // console.log('更新同步范围col', syncLeftCol, syncRightCol); + for (let col = syncLeftCol; col <= syncRightCol; col++) { + const colGroup = proxy.table.scenegraph.getColGroup(col); + updateColGroupContent(colGroup, proxy); + } + + // for test + const cellGroup = proxy.table.scenegraph.getCell(screenLeftCol, 0); + cellGroup.AABBBounds.width(); + console.log('leftCell', cellGroup.col, cellGroup.globalAABBBounds, cellGroup); + + proxy.colStart = distStartCol; + proxy.colEnd = distEndCol; + proxy.currentCol = direction === 'left' ? proxy.currentCol + count : proxy.currentCol - count; + proxy.totalCol = direction === 'left' ? proxy.totalCol + count : proxy.totalCol - count; + proxy.referenceCol = proxy.colStart + Math.floor((proxy.colEnd - proxy.colStart) / 2); + proxy.colUpdatePos = proxy.colStart; + proxy.colUpdateDirection = distEndCol > proxy.bodyRightCol - (proxy.colEnd - proxy.colStart + 1) ? 'right' : 'left'; + // console.log('sync', proxy.referenceCol, proxy.colStart, proxy.colEnd); + // console.log('move total end proxy col', proxy.colStart, proxy.colEnd); + // console.log( + // 'move total end cell col', + // (proxy.table as any).scenegraph.bodyGroup.firstChild.row, + // (proxy.table as any).scenegraph.bodyGroup.lastChild.row + // ); + // proxy.table.scenegraph.stage.render(); + + await proxy.progress(); + } +} + +function updateColGroupPosition(colGroup: Group, newCol: number, x: number) { + // 更新位置&col + colGroup.col = newCol; + colGroup.forEachChildren((cellGroup: Group) => { + cellGroup.col = newCol; + cellGroup.needUpdate = true; + }); + colGroup.setAttribute('x', x); + colGroup.needUpdate = true; +} + +function updateColGroupContent(colGroup: Group, proxy: SceneProxy) { + // colGroup.forEachChildren((cellGroup: Group) => { + // proxy.updateCellGroupContent(cellGroup); + // }); + // for (let row = (colGroup.firstChild as Group).row; row <= (colGroup.lastChild as Group).row; row++) { + // const cellGroup = proxy.highPerformanceGetCell(colGroup.col, row); + // proxy.updateCellGroupContent(cellGroup); + // } + let cellGroup = colGroup.firstChild; + while (cellGroup) { + const newCellGroup = proxy.updateCellGroupContent(cellGroup as Group); + cellGroup = newCellGroup._next; + } + colGroup.needUpdate = false; +} diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts new file mode 100644 index 000000000..b99b6a821 --- /dev/null +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts @@ -0,0 +1,199 @@ +import type { Group } from '../../../graphic/group'; +import { computeRowsHeight } from '../../../layout/compute-row-height'; +import type { SceneProxy } from '../proxy'; +import { updateAutoRow } from './update-auto-row'; + +export async function dynamicSetY(y: number, proxy: SceneProxy) { + // 计算变动row range + // const screenTopRow = proxy.table.getRowAt(y).row; + const screenTop = (proxy.table as any).getTargetRowAt(y + proxy.table.scenegraph.colHeaderGroup.attribute.height); + if (!screenTop) { + return; + } + const screenTopRow = screenTop.row; + proxy.screenTopRow = screenTopRow; + const deltaRow = screenTopRow - proxy.referenceRow; + if (deltaRow > 0) { + // 向下滚动,顶部cell group移到底部 + moveCell(deltaRow, 'up', screenTopRow, proxy); + proxy.updateBody(y); + // if (proxy.rowEnd === proxy.table.scenegraph.proxy.bodyBottomRow) { + // const totalHeight = proxy.table.getAllRowsHeight(); + // const top = totalHeight - proxy.table.scenegraph.height; + // proxy.updateBody(top); + // } else { + // proxy.updateBody(y); + // } + } else if (deltaRow < 0) { + // 向上滚动,底部cell group移到顶部 + moveCell(-deltaRow, 'down', screenTopRow, proxy); + proxy.updateBody(y); + // if (proxy.rowStart === proxy.bodyTopRow) { + // proxy.updateBody(0); + // } else { + // proxy.updateBody(y); + // } + } else { + // 不改变row,更新body group范围 + proxy.updateBody(y); + } + + proxy.table.scenegraph.updateNextFrame(); +} + +async function moveCell(count: number, direction: 'up' | 'down', screenTopRow: number, proxy: SceneProxy) { + // 限制count范围 + if (direction === 'up' && proxy.rowEnd + count > proxy.bodyBottomRow) { + count = proxy.bodyBottomRow - proxy.rowEnd; + } else if (direction === 'down' && proxy.rowStart - count < proxy.bodyTopRow) { + count = proxy.rowStart - proxy.bodyTopRow; + } + + // 两种更新模式 + // 1. count < rowEnd - rowStart:从顶/底部移动count数量的单元格到底/顶部 + // 2. count >= rowEnd - rowStart:整体移动到目标位置 + if (count < proxy.rowEnd - proxy.rowStart) { + // 计算更新区域 + const startRow = direction === 'up' ? proxy.rowStart : proxy.rowEnd - count + 1; + const endRow = direction === 'up' ? proxy.rowStart + count - 1 : proxy.rowEnd; + // console.log('move', startRow, endRow, direction); + for (let col = proxy.bodyLeftCol; col <= proxy.bodyRightCol; col++) { + const colGroup = proxy.table.scenegraph.getColGroup(col); + for (let row = startRow; row <= endRow; row++) { + if (direction === 'up') { + const cellGroup = colGroup.firstChild as Group; + proxy.updateCellGroupPosition( + cellGroup, + (colGroup.lastChild as Group).row + 1, + (colGroup.lastChild as Group).attribute.y + (colGroup.lastChild as Group).attribute.height + ); + colGroup.appendChild(cellGroup); + } else { + const cellGroup = colGroup.lastChild as Group; + proxy.updateCellGroupPosition( + cellGroup, + (colGroup.firstChild as Group).row - 1, + (colGroup.firstChild as Group).attribute.y - cellGroup.attribute.height + ); + colGroup.insertBefore(cellGroup, colGroup.firstChild); + } + } + } + const distStartRow = direction === 'up' ? proxy.rowEnd + 1 : proxy.rowStart - count; + const distEndRow = direction === 'up' ? proxy.rowEnd + count : proxy.rowStart - 1; + + // 更新同步范围 + const syncTopRow = Math.max(proxy.bodyTopRow, screenTopRow - proxy.screenRowCount * 1); + const syncBottomRow = Math.min(proxy.bodyBottomRow, screenTopRow + proxy.screenRowCount * 2); + if (proxy.table.internalProps.autoRowHeight) { + computeRowsHeight(proxy.table, syncTopRow, syncBottomRow); + } + for (let col = proxy.bodyLeftCol; col <= proxy.bodyRightCol; col++) { + for (let row = syncTopRow; row <= syncBottomRow; row++) { + // const cellGroup = proxy.table.scenegraph.getCell(col, row); + const cellGroup = proxy.highPerformanceGetCell(col, row, distStartRow, distEndRow); + proxy.updateCellGroupContent(cellGroup); + } + } + if (proxy.table.internalProps.autoRowHeight) { + updateAutoRow( + proxy.bodyLeftCol, // colStart + proxy.bodyRightCol, // colEnd + syncTopRow, // rowStart + syncBottomRow, // rowEnd + proxy.table, + direction + ); + } + + proxy.rowStart = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; + proxy.rowEnd = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; + proxy.currentRow = direction === 'up' ? proxy.currentRow + count : proxy.currentRow - count; + proxy.totalRow = direction === 'up' ? proxy.totalRow + count : proxy.totalRow - count; + proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); + proxy.rowUpdatePos = distStartRow; + proxy.rowUpdateDirection = direction; + console.log('move end proxy', proxy.rowStart, proxy.rowEnd); + console.log( + 'move end cell', + (proxy.table as any).scenegraph.bodyGroup.firstChild.firstChild.row, + (proxy.table as any).scenegraph.bodyGroup.firstChild.lastChild.row + ); + + proxy.table.scenegraph.updateNextFrame(); + await proxy.progress(); + } else { + const distStartRow = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; + const distEndRow = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; + const distStartRowY = proxy.table.getRowsHeight(proxy.bodyTopRow, distStartRow - 1); + for (let col = proxy.bodyLeftCol; col <= proxy.bodyRightCol; col++) { + const colGroup = proxy.table.scenegraph.getColGroup(col); + colGroup?.forEachChildren((cellGroup: Group, index) => { + // 这里使用colGroup变量而不是for proxy.rowStart to proxy.rowEndproxy.rowEnd是因为在更新内可能出现row号码重复的情况 + proxy.updateCellGroupPosition( + cellGroup, + direction === 'up' ? cellGroup.row + count : cellGroup.row - count, + index === 0 // row === proxy.rowStart + ? distStartRowY + : (cellGroup._prev as Group).attribute.y + (cellGroup._prev as Group).attribute.height + ); + }); + } + + // 更新同步范围 + let syncTopRow; + let syncBottomRow; + if (proxy.table.internalProps.autoRowHeight) { + syncTopRow = distStartRow; + syncBottomRow = distEndRow; + } else { + syncTopRow = Math.max(proxy.bodyTopRow, screenTopRow - proxy.screenRowCount * 1); + syncBottomRow = Math.min(proxy.bodyBottomRow, screenTopRow + proxy.screenRowCount * 2); + } + console.log('更新同步范围', syncTopRow, syncBottomRow); + if (proxy.table.internalProps.autoRowHeight) { + computeRowsHeight(proxy.table, syncTopRow, syncBottomRow); + } + proxy.rowStart = distStartRow; + proxy.rowEnd = distEndRow; + for (let col = proxy.bodyLeftCol; col <= proxy.bodyRightCol; col++) { + for (let row = syncTopRow; row <= syncBottomRow; row++) { + // const cellGroup = proxy.table.scenegraph.getCell(col, row); + const cellGroup = proxy.highPerformanceGetCell(col, row, distStartRow, distEndRow); + proxy.updateCellGroupContent(cellGroup); + } + } + console.log( + 'updateAutoRow', + distEndRow > proxy.bodyBottomRow - (proxy.rowEnd - proxy.rowStart + 1) ? 'down' : 'up' + ); + + if (proxy.table.internalProps.autoRowHeight) { + updateAutoRow( + proxy.bodyLeftCol, // colStart + proxy.bodyRightCol, // colEnd + syncTopRow, // rowStart + syncBottomRow, // rowEnd + proxy.table, + distEndRow > proxy.bodyBottomRow - (proxy.rowEnd - proxy.rowStart + 1) ? 'down' : 'up' // 跳转到底部时,从下向上对齐 + ); + } + + proxy.currentRow = direction === 'up' ? proxy.currentRow + count : proxy.currentRow - count; + proxy.totalRow = direction === 'up' ? proxy.totalRow + count : proxy.totalRow - count; + proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); + proxy.rowUpdatePos = proxy.rowStart; + proxy.rowUpdateDirection = distEndRow > proxy.bodyBottomRow - (proxy.rowEnd - proxy.rowStart + 1) ? 'down' : 'up'; + console.log('move total end proxy', proxy.rowStart, proxy.rowEnd); + console.log( + 'move total end cell', + (proxy.table as any).scenegraph.bodyGroup.firstChild.firstChild.row, + (proxy.table as any).scenegraph.bodyGroup.firstChild.lastChild.row + ); + + proxy.table.scenegraph.updateNextFrame(); + if (!proxy.table.internalProps.autoRowHeight) { + await proxy.progress(); + } + } +} diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts new file mode 100644 index 000000000..2b8e9f6c1 --- /dev/null +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts @@ -0,0 +1,74 @@ +import type { BaseTableAPI } from '../../../../ts-types/base-table'; +import type { Group } from '../../../graphic/group'; + +export function updateAutoRow( + colStart: number, + colEnd: number, + rowStart: number, + rowEnd: number, + table: BaseTableAPI, + direction: 'up' | 'down' = 'up' +) { + // // 获取行高 + // for (let row = rowStart; row <= rowEnd; row++) { + // let maxRowHeight = 0; + // for (let col = colStart; col <= colEnd; col++) { + // const cellGroup = table.scenegraph.highPerformanceGetCell(col, row); + // if (!cellGroup.row) { + // continue; + // } + // // const contentHeight = cellGroup.getContentHeight(); + // const text = (cellGroup.getChildByName('text') as WrapText) || cellGroup.getChildByName('content'); + // const headerStyle = table._getCellStyle(col, row); + // const padding = getQuadProps(getProp('padding', headerStyle, col, row, table)); + // const height = text.AABBBounds.height() + (padding[0] + padding[2]); + // maxRowHeight = Math.max(maxRowHeight, height); + // (cellGroup as any).needUpdateForAutoRowHeight = false; + // } + // // updateRowHeight(table.scenegraph, row, table.getRowHeight(row) - maxRowHeight); + // for (let col = colStart; col <= colEnd; col++) { + // const cellGroup = table.scenegraph.highPerformanceGetCell(col, row); + // updateCellHeightForColumn(table.scenegraph, cellGroup, col, row, maxRowHeight, 0, false); + // } + + // table.setRowHeight(row, maxRowHeight, true); + // } + + // 更新y位置 + if (direction === 'up') { + for (let col = colStart; col <= colEnd; col++) { + for (let row = rowStart; row <= rowEnd; row++) { + const cellGroup = table.scenegraph.getCell(col, row); + if (!cellGroup.row) { + continue; + } + let y; + if (cellGroup._prev) { + y = ((cellGroup._prev as Group)?.attribute.y ?? 0) + ((cellGroup._prev as Group)?.attribute.height ?? 0); + } else { + // 估计位置 + y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row - 1); + } + cellGroup.setAttribute('y', y); + } + } + } else { + for (let col = colStart; col <= colEnd; col++) { + for (let row = rowEnd; row >= rowStart; row--) { + const cellGroup = table.scenegraph.getCell(col, row); + if (!cellGroup.row) { + continue; + } + let y; + if (cellGroup._next) { + y = ((cellGroup._next as Group)?.attribute.y ?? 0) - (cellGroup.attribute.height ?? 0); + } else { + // 估计位置 + y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row) - (cellGroup.attribute.height ?? 0); + console.log('估计位置', table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row)); + } + cellGroup.setAttribute('y', y); + } + } + } +} diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index 947a90997..9735fd7df 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -8,16 +8,27 @@ import { getQuadProps } from '../utils/padding'; import { getProp } from '../utils/get-prop'; import type { BaseTableAPI } from '../../ts-types/base-table'; -export function computeColsWidth(table: BaseTableAPI, update?: boolean): void { +export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?: number, update?: boolean): void { const time = typeof window !== 'undefined' ? window.performance.now() : 0; - table._clearColRangeWidthsMap(); + colStart = colStart ?? 0; + colEnd = colEnd ?? table.colCount - 1; + // table._clearColRangeWidthsMap(); + // clear colRangeWidthsMap + if (colStart === 0 && colEnd === table.colCount - 1) { + table._clearColRangeWidthsMap(); + // } else { + // for (let col = colStart; col <= colEnd; col++) { + // table._clearColRangeWidthsMap(col); + // } + } + const oldColWidths = []; if (update) { for (let col = 0; col < table.colCount; col++) { oldColWidths.push(table.getColWidth(col)); } } - for (let col = 0; col < table.colCount; col++) { + for (let col = colStart; col <= colEnd; col++) { let maxWidth; if ( !table.internalProps.transpose && @@ -44,6 +55,11 @@ export function computeColsWidth(table: BaseTableAPI, update?: boolean): void { } table._setColContentWidth(col, maxWidth); + + const oldWidth = table.getColWidth(col); + if (oldWidth !== maxWidth) { + table._clearColRangeWidthsMap(col); + } table.setColWidth(col, maxWidth, false, true); } // 处理adaptive宽度 @@ -88,7 +104,7 @@ export function computeColsWidth(table: BaseTableAPI, update?: boolean): void { } } } - console.log('computeColsWidth time:', (typeof window !== 'undefined' ? window.performance.now() : 0) - time); + // console.log('computeColsWidth time:', (typeof window !== 'undefined' ? window.performance.now() : 0) - time); if (update) { for (let col = 0; col < table.colCount; col++) { @@ -388,7 +404,7 @@ function computeTextWidth(col: number, row: number, table: BaseTableAPI): number return maxWidth; } -function getCellRect(col: number, row: number, table: BaseTableAPI) { +export function getCellRect(col: number, row: number, table: BaseTableAPI) { return { left: 0, top: 0, diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts new file mode 100644 index 000000000..8932d5222 --- /dev/null +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -0,0 +1,290 @@ +import { RichText } from '@visactor/vrender'; +import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; +import { validToString } from '../../tools/util'; +import type { ColumnIconOption } from '../../ts-types'; +import { IconPosition } from '../../ts-types'; +import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; +import type { ColumnData, TextColumnDefine } from '../../ts-types/list-table/layout-map/api'; +import { WrapText } from '../graphic/text'; +import { getProp } from '../utils/get-prop'; +import { getQuadProps } from '../utils/padding'; +import { getCellRect } from './compute-col-width'; +import { dealWithRichTextIcon } from '../utils/text-icon-layout'; + +const utilTextMark = new WrapText({ + autoWrapText: true +}); +const utilRichTextMark = new RichText({ + width: 0, + height: 0, + textConfig: [] +}); + +export function computeRowsHeight(table: BaseTableAPI, rowStart?: number, rowEnd?: number): void { + if (!table.internalProps.autoRowHeight) { + // autoRowHeight false use default height + return; + } + rowStart = rowStart ?? 0; + rowEnd = rowEnd ?? table.rowCount - 1; + const time = typeof window !== 'undefined' ? window.performance.now() : 0; + + // clear rowRangeHeightsMap + if (rowStart === 0 && rowEnd === table.rowCount - 1) { + table._clearRowRangeHeightsMap(); + } else { + for (let row = rowStart; row <= rowEnd; row++) { + table._clearRowRangeHeightsMap(row); + } + } + + // compute header row in column header row + for (let row = rowStart; row < table.columnHeaderLevelCount; row++) { + const height = computeRowHeight(row, 0, table.colCount - 1, table); + table.setRowHeight(row, height); + } + + if (rowEnd < table.columnHeaderLevelCount) { + return; + } + + // compute body row + if ( + !table.internalProps.transpose && + !(table.isPivotTable() && (table.internalProps.layoutMap as PivotHeaderLayoutMap).indicatorsAsCol) && + checkFixedStyleAndNoWrap(table) + ) { + // check fixed style and no wrap situation, fill all row width single compute + // traspose table and row indicator pivot table cannot use single row height + const height = computeRowHeight(table.columnHeaderLevelCount, 0, table.colCount - 1, table); + fillRowsHeight(height, table.columnHeaderLevelCount, table.rowCount - 1, table); + } else if ( + (table.internalProps.transpose || + (table.isPivotTable() && !(table.internalProps.layoutMap as PivotHeaderLayoutMap).indicatorsAsCol)) && + checkFixedStyleAndNoWrap(table) + ) { + // check fixed style and no wrap situation, just compute 0-table.rowHeaderLevelCount column(the column after row header) in ervey row + // in traspose table and row indicator pivot table + for (let row = Math.max(rowStart, table.columnHeaderLevelCount); row <= rowEnd; row++) { + table._clearRowRangeHeightsMap(row); + const height = computeRowHeight(row, 0, table.rowHeaderLevelCount, table); + table.setRowHeight(row, height); + } + } else { + for (let row = Math.max(rowStart, table.columnHeaderLevelCount); row <= rowEnd; row++) { + table._clearRowRangeHeightsMap(row); + const height = computeRowHeight(row, 0, table.colCount - 1, table); + table.setRowHeight(row, height); + } + } + + console.log('computeRowsHeight time:', (typeof window !== 'undefined' ? window.performance.now() : 0) - time); +} + +export function computeRowHeight(row: number, startCol: number, endCol: number, table: BaseTableAPI): number { + let maxHeight = 0; + for (let col = startCol; col <= endCol; col++) { + // CustomRender height calculation + const customHeight = computeCustomRenderHeight(col, row, table); + if (typeof customHeight === 'number') { + maxHeight = Math.max(customHeight, maxHeight); + continue; + } + + // text height calculation + const textHeight = computeTextHeight(col, row, table); + maxHeight = Math.max(textHeight, maxHeight); + } + return maxHeight; +} + +function checkFixedStyleAndNoWrap(table: BaseTableAPI): boolean { + const { layoutMap } = table.internalProps; + const row = table.columnHeaderLevelCount; + for (let col = 0; col < table.colCount; col++) { + const isHeader = layoutMap.isHeader(col, row); + const cellDefine = isHeader ? layoutMap.getHeader(col, row) : layoutMap.getBody(col, row); + if ( + typeof cellDefine.style === 'function' || + typeof (cellDefine as ColumnData).icon === 'function' || + typeof (cellDefine as HeaderData).headerIcon === 'function' || + (isHeader ? cellDefine.define?.headerCustomRender : cellDefine.define?.customRender) || + (isHeader ? typeof cellDefine.define?.headerIcon === 'function' : typeof cellDefine.define?.icon === 'function') + ) { + return false; + } + const cellStyle = table._getCellStyle(col, row); + if ( + typeof cellStyle.padding === 'function' || + typeof cellStyle.fontSize === 'function' || + typeof cellStyle.lineHeight === 'function' || + cellStyle.autoWrapText === true + ) { + return false; + } + } + + return true; +} + +function fillRowsHeight(height: number, startRow: number, endRow: number, table: BaseTableAPI) { + for (let row = startRow; row <= endRow; row++) { + table.setRowHeight(row, height); + } +} + +/** + * @description: compute customRender height + * @param {number} col + * @param {number} row + * @param {BaseTableAPI} table + * @return {*} + */ +function computeCustomRenderHeight(col: number, row: number, table: BaseTableAPI): number | undefined { + const customRender = table.getCustomRender(col, row); + const customLayout = table.getCustomLayout(col, row); + if (customRender || customLayout) { + let spanCol = 1; + let height = 0; + if (table.isHeader(col, row) || (table.getBodyColumnDefine(col, row) as TextColumnDefine).mergeCell) { + const cellRange = table.getCellRange(col, row); + spanCol = cellRange.end.col - cellRange.start.col + 1; + } + const arg = { + col, + row, + dataValue: table.getCellOriginValue(col, row), + value: table.getCellValue(col, row) || '', + rect: getCellRect(col, row, table), + table + }; + if (customLayout) { + // 处理customLayout + const customLayoutObj = customLayout(arg); + customLayoutObj.rootContainer.isRoot = true; + const size = customLayoutObj.rootContainer.getContentSize(); + height = size.height ?? 0; + } else if (typeof customRender === 'function') { + // 处理customRender + const customRenderObj = customRender(arg); + height = customRenderObj?.expectedHeight ?? 0; + } else { + height = customRender?.expectedHeight ?? 0; + } + return height / spanCol; + } + return undefined; +} + +/** + * @description: compute text height + * @param {number} col + * @param {number} row + * @param {BaseTableAPI} table + * @return {*} + */ +function computeTextHeight(col: number, row: number, table: BaseTableAPI): number { + let maxHeight = 0; + const cellValue = table.getCellValue(col, row); + // const dataValue = table.getCellOriginValue(col, row); + const actStyle = table._getCellStyle(col, row); + let iconHeight = 0; + let iconWidth = 0; + const iconInlineFront: ColumnIconOption[] = []; + let iconInlineFrontHeight = 0; + const iconInlineEnd: ColumnIconOption[] = []; + let iconInlineEndHeight = 0; + const define = table.getBodyColumnDefine(col, row); + const mayHaveIcon = table.getCellType(col, row) !== 'body' ? true : !!define?.icon || !!define?.tree; + if (mayHaveIcon) { + const icons = table.getCellIcons(col, row); + icons?.forEach(icon => { + if ( + icon.positionType !== IconPosition.absoluteRight && + icon.positionType !== IconPosition.inlineFront && + icon.positionType !== IconPosition.inlineEnd + ) { + iconWidth += (icon.width ?? 0) + (icon.marginLeft ?? 0) + (icon.marginRight ?? 0); + iconHeight = Math.max(iconHeight, icon.height ?? 0); + } else if (icon.positionType === IconPosition.inlineFront) { + iconInlineFront.push(icon); + iconInlineFrontHeight = Math.max( + iconInlineFrontHeight, + (icon.height ?? 0) + (icon.marginLeft ?? 0) + (icon.marginRight ?? 0) + ); + } else if (icon.positionType === IconPosition.inlineEnd) { + iconInlineEnd.push(icon); + iconInlineEndHeight = Math.max( + iconInlineEndHeight, + (icon.height ?? 0) + (icon.marginLeft ?? 0) + (icon.marginRight ?? 0) + ); + } + }); + } + let spanRow = 1; + if (table.isHeader(col, row) || (table.getBodyColumnDefine(col, row) as TextColumnDefine).mergeCell) { + const cellRange = table.getCellRange(col, row); + spanRow = cellRange.end.row - cellRange.start.row + 1; + } + + const padding = getQuadProps(getProp('padding', actStyle, col, row, table)); + const fontSize = getProp('fontSize', actStyle, col, row, table); + const fontStyle = getProp('fontStyle', actStyle, col, row, table); + const fontWeight = getProp('fontWeight', actStyle, col, row, table); + const lineHeight = getProp('lineHeight', actStyle, col, row, table) ?? fontSize; + const fontFamily = getProp('fontFamily', actStyle, col, row, table); + const autoWrapText = getProp('autoWrapText', actStyle, col, row, table); + const lines = validToString(cellValue).split('\n') || []; + + if (iconInlineFront.length || iconInlineEnd.length) { + // if (autoWrapText) { + const textOption = Object.assign({ + text: cellValue?.toString(), + fontFamily, + fontSize, + fontStyle, + fontWeight, + lineHeight + }); + textOption.textBaseline = 'middle'; + const textConfig = [ + ...iconInlineFront.map(icon => dealWithRichTextIcon(icon)), + textOption, + ...iconInlineEnd.map(icon => dealWithRichTextIcon(icon)) + ]; + utilRichTextMark.setAttributes({ + width: table.getColWidth(col) - (padding[1] + padding[3]) - iconWidth, + height: 0, + textConfig + }); + maxHeight = utilRichTextMark.AABBBounds.height(); + // } else { + // maxHeight = 0; + // lines.forEach((line: string, index: number) => { + // if (index === 0 && iconInlineFront.length) { + // maxHeight += Math.max(lineHeight, iconInlineFrontHeight); + // } else if (index === lines.length - 1 && iconInlineEnd.length) { + // maxHeight += Math.max(lineHeight, iconInlineEndHeight); + // } else { + // maxHeight += lineHeight; + // } + // }); + // } + } else if (autoWrapText) { + const maxLineWidth = table.getColWidth(col) - (padding[1] + padding[3]) - iconWidth; + utilTextMark.setAttributes({ + maxLineWidth, + text: lines, + fontSize, + fontStyle, + fontWeight, + fontFamily + }); + maxHeight = utilTextMark.AABBBounds.height(); + } else { + // autoWrapText = false + maxHeight = lines.length * lineHeight; + } + + return (Math.max(maxHeight, iconHeight) + padding[0] + padding[2]) / spanRow; +} diff --git a/packages/vtable/src/scenegraph/layout/update-height.ts b/packages/vtable/src/scenegraph/layout/update-height.ts index ce130b24e..055e63466 100644 --- a/packages/vtable/src/scenegraph/layout/update-height.ts +++ b/packages/vtable/src/scenegraph/layout/update-height.ts @@ -10,6 +10,7 @@ import { updateCellContentHeight } from '../utils/text-icon-layout'; import type { IProgressbarColumnBodyDefine } from '../../ts-types/list-table/define/progressbar-define'; import { dealWithCustom } from '../component/custom'; import { updateImageCellContentWhileResize } from '../group-creater/cell-type/image-cell'; +import { getStyleTheme } from '../../core/tableHelper'; export function updateRowHeight(scene: Scenegraph, row: number, detaY: number) { for (let col = 0; col < scene.table.colCount; col++) { @@ -209,7 +210,8 @@ export function updateCellHeight( cell.attribute.width, cell.attribute.height, padding, - scene.table + scene.table, + getStyleTheme(headerStyle, scene.table, col, row, getProp).theme ); } else if (type === 'image' || type === 'video') { updateImageCellContentWhileResize(cell, col, row, scene.table); diff --git a/packages/vtable/src/scenegraph/layout/update-width.ts b/packages/vtable/src/scenegraph/layout/update-width.ts index 390ead3e8..20b4ddd65 100644 --- a/packages/vtable/src/scenegraph/layout/update-width.ts +++ b/packages/vtable/src/scenegraph/layout/update-width.ts @@ -1,4 +1,5 @@ import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; +import { getStyleTheme } from '../../core/tableHelper'; import type { IProgressbarColumnBodyDefine } from '../../ts-types/list-table/define/progressbar-define'; import type { Group } from '../graphic/group'; import type { Icon } from '../graphic/icon'; @@ -252,7 +253,8 @@ function updateCellWidth( cellGroup.attribute.width, cellGroup.attribute.height, padding, - scene.table + scene.table, + getStyleTheme(headerStyle, scene.table, col, row, getProp).theme ); } else if (type === 'image' || type === 'video') { // // 只更新背景边框 diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index fad6f3580..d645c5f46 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -35,6 +35,7 @@ import { moveSelectingRangeComponentsToSelectedRangeComponents } from './select/ import { deleteAllSelectBorder, deleteLastSelectedRangeComponents } from './select/delete-select-border'; import { updateRow } from './layout/update-row'; import { handleTextStick } from './stick-text'; +import { computeRowsHeight } from './layout/compute-row-height'; import { emptyGroup } from './utils/empty-group'; import { updateChartSize } from './refresh-node/update-chart'; import { dealFrozen, resetFrozen } from './layout/frozen'; @@ -285,8 +286,6 @@ export class Scenegraph { */ createSceneGraph() { this.clear = false; - computeColsWidth(this.table); - this.frozenColCount = this.table.rowHeaderLevelCount; this.frozenRowCount = this.table.columnHeaderLevelCount; @@ -295,50 +294,14 @@ export class Scenegraph { // update table group position for cell group global position, not create border yet. createFrameBorder(this.tableGroup, this.table.theme.frameStyle, this.tableGroup.role, undefined, true); - // 首屏表头全量 - this.createHeaderSceneGraph(); - // body生成首屏 - if (this.transpose || this.isPivot) { - this.createBodySceneGraph(); - } else { - this.createBodySceneGraphForFirstScreen(); - } - } - - createHeaderSceneGraph() { - createCornerHeaderColGroup(this.cornerHeaderGroup, 0, 0, this.table); - this.colHeaderGroup.setAttribute('x', this.cornerHeaderGroup.attribute.width); - createColHeaderColGroup(this.colHeaderGroup, 0, 0, this.table); - } - - createBodySceneGraph() { - // 依据列表头高度更新行表头Group y - this.rowHeaderGroup.setAttribute('y', this.colHeaderGroup.attribute.height); - createRowHeaderColGroup(this.rowHeaderGroup, 0, 0, this.table); - - // 依据列表头高度和行表头宽度,更新内容Group xy - this.bodyGroup.setAttributes({ - y: this.colHeaderGroup.attribute.height, - x: this.rowHeaderGroup.attribute.width - }); - createBodyColGroup(this.bodyGroup, 0, 0, this.table); - this.afterScenegraphCreated(); - } - - createBodySceneGraphForFirstScreen() { - // 依据列表头高度更新行表头Group y - this.rowHeaderGroup.setAttribute('y', this.colHeaderGroup.attribute.height); - // createRowHeaderColGroup(this.rowHeaderGroup, 0, 0, this.table); - // this.proxy.createBodyColGroupForFirstScreen(this.rowHeaderGroup, 0, 0, this.table, 'rowHeader'); - - // 依据列表头高度和行表头宽度,更新内容Group xy - this.bodyGroup.setAttributes({ - y: this.colHeaderGroup.attribute.height, - x: this.rowHeaderGroup.attribute.width - }); - console.log('before-createBodyColGroupForFirstScreen'); - this.proxy.createColGroupForFirstScreen(this.rowHeaderGroup, this.bodyGroup, 0, 0, this.table); - console.log('after-createBodyColGroupForFirstScreen'); + this.proxy.createGroupForFirstScreen( + this.cornerHeaderGroup, + this.colHeaderGroup, + this.rowHeaderGroup, + this.bodyGroup, + 0, + 0 + ); this.afterScenegraphCreated(); } @@ -424,11 +387,11 @@ export class Scenegraph { return cell || emptyGroup; } - highPerformanceGetCell(col: number, row: number): Group { - if (!this.isPivot && !this.transpose && !this.table.isHeader(col, row)) { - return this.proxy.highPerformanceGetCell(col, row, 0, this.table.rowCount - 1); + highPerformanceGetCell(col: number, row: number, getShadow?: boolean): Group { + if (!this.table.isHeader(col, row)) { + return this.proxy.highPerformanceGetCell(col, row, 0, this.table.rowCount - 1, getShadow); } - return this.getCell(col, row); + return this.getCell(col, row, getShadow); } getColGroup(col: number, isCornerOrColHeader = false): Group { @@ -704,13 +667,17 @@ export class Scenegraph { * recalculates column width in all autowidth columns */ recalculateColWidths() { - computeColsWidth(this.table, true); + computeColsWidth(this.table, 0, this.table.colCount - 1, true); + } + + recalculateRowHeights() { + computeRowsHeight(this.table, 0, this.table.rowCount - 1); } resize() { this.recalculateColWidths(); if (this.table.internalProps.autoRowHeight) { - updateAutoRowHeight(this, true); + this.recalculateRowHeights(); } this.dealWidthMode(); this.dealFrozen(); @@ -810,16 +777,17 @@ export class Scenegraph { * @return {*} */ setX(x: number) { - if (this.colHeaderGroup.attribute.width + x === this.bodyGroup.attribute.x) { - return; - } - // this.tableGroup.setAttribute('x', x); - // this.tableGroup.setAttribute('width', this.table.tableNoFrameWidth - x); - this.bodyGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); - this.colHeaderGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); + // if (this.colHeaderGroup.attribute.width + x === this.bodyGroup.attribute.x) { + // return; + // } + // // this.tableGroup.setAttribute('x', x); + // // this.tableGroup.setAttribute('width', this.table.tableNoFrameWidth - x); + // this.bodyGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); + // this.colHeaderGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); - // (this.tableGroup.lastChild as any).setAttribute('width', this.table.tableNoFrameWidth - x); - this.updateNextFrame(); + // // (this.tableGroup.lastChild as any).setAttribute('width', this.table.tableNoFrameWidth - x); + // this.updateNextFrame(); + this.table.scenegraph.proxy.setX(-x); } /** @@ -828,18 +796,18 @@ export class Scenegraph { * @return {*} */ setY(y: number) { - if (this.transpose || this.isPivot) { - if (this.colHeaderGroup.attribute.height + y === this.bodyGroup.attribute.y) { - return; - } - this.bodyGroup.setAttribute('y', this.colHeaderGroup.attribute.height + y); - this.rowHeaderGroup.setAttribute('y', this.colHeaderGroup.attribute.height + y); - // this.tableGroup.setAttribute('height', this.table.tableNoFrameHeight - y); - // (this.tableGroup.lastChild as any).setAttribute('width', this.table.tableNoFrameWidth - x); - this.updateNextFrame(); - } else if (this.table.scenegraph.proxy) { - this.table.scenegraph.proxy.setY(-y); - } + // if (this.transpose || this.isPivot) { + // if (this.colHeaderGroup.attribute.height + y === this.bodyGroup.attribute.y) { + // return; + // } + // this.bodyGroup.setAttribute('y', this.colHeaderGroup.attribute.height + y); + // this.rowHeaderGroup.setAttribute('y', this.colHeaderGroup.attribute.height + y); + // // this.tableGroup.setAttribute('height', this.table.tableNoFrameHeight - y); + // // (this.tableGroup.lastChild as any).setAttribute('width', this.table.tableNoFrameWidth - x); + // this.updateNextFrame(); + // } else if (this.table.scenegraph.proxy) { + this.table.scenegraph.proxy.setY(-y); + // } } /** @@ -858,6 +826,20 @@ export class Scenegraph { this.updateNextFrame(); } + /** + * @description: 更新表格的x位置,滚动中使用 + * @param {number} x + * @return {*} + */ + setBodyAndColHeaderX(x: number) { + if (this.rowHeaderGroup.attribute.width + x === this.bodyGroup.attribute.x) { + return; + } + this.bodyGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); + this.colHeaderGroup.setAttribute('x', this.rowHeaderGroup.attribute.width + x); + this.updateNextFrame(); + } + /** * @description: 完成创建场景树节点后,处理自动行高列宽 * @return {*} @@ -866,10 +848,10 @@ export class Scenegraph { // 对齐auto列宽 // updateAutoColWidth(this); // 对齐autoWrapText - const { autoRowHeight } = this.table.internalProps; - if (autoRowHeight) { - updateAutoRowHeight(this); - } + // const { autoRowHeight } = this.table.internalProps; + // if (autoRowHeight) { + // updateAutoRowHeight(this); + // } this.dealWidthMode(); @@ -1338,9 +1320,9 @@ export class Scenegraph { updateCellContent(col: number, row: number) { if (this.clear) { - return; + return undefined; } - updateCell(col, row, this.table); + return updateCell(col, row, this.table); } setPixelRatio(pixelRatio: number) { @@ -1371,7 +1353,7 @@ export class Scenegraph { // update column width and row height this.recalculateColWidths(); if (this.table.internalProps.autoRowHeight) { - updateAutoRowHeight(this, true); + this.recalculateRowHeights(); } // check frozen status diff --git a/packages/vtable/src/scenegraph/stick-text/index.ts b/packages/vtable/src/scenegraph/stick-text/index.ts index a5a6f3fad..a0d74bb79 100644 --- a/packages/vtable/src/scenegraph/stick-text/index.ts +++ b/packages/vtable/src/scenegraph/stick-text/index.ts @@ -4,6 +4,7 @@ import { PIVOT_TABLE_EVENT_TYPE } from '../../ts-types/pivot-table/PIVOT_TABLE_E import type { Group } from '../graphic/group'; import type { WrapText } from '../graphic/text'; import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; +import type { ITextStyleOption } from '../../ts-types'; const changedCells: { col: number; row: number }[] = []; export function handleTextStick(table: BaseTableAPI) { changedCells.forEach(cellPos => { @@ -133,3 +134,21 @@ function adjustCellContentHorizontalLayout(cellGroup: Group, minLeft: number, ma }); } } + +export function checkHaveTextStick(table: BaseTableAPI) { + const headerObjects = table.internalProps.layoutMap.headerObjects; + const columnObjects = table.internalProps.layoutMap.columnObjects; + for (let i = 0; i < headerObjects.length; i++) { + const header = headerObjects[i]; + if (header && (header.define.headerStyle as ITextStyleOption)?.textStick) { + return true; + } + } + for (let i = 0; i < columnObjects.length; i++) { + const column = columnObjects[i]; + if (column && (column.define.style as ITextStyleOption)?.textStick) { + return true; + } + } + return false; +} diff --git a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts index 1bcb21d6d..ba0bd55e7 100644 --- a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts +++ b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts @@ -50,7 +50,7 @@ export function createCellContent( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, table: BaseTableAPI, - cellTheme?: IThemeSpec + cellTheme: IThemeSpec ) { const leftIcons: ColumnIconOption[] = []; const rightIcons: ColumnIconOption[] = []; @@ -89,9 +89,7 @@ export function createCellContent( pickable: false, dx: hierarchyOffset }; - const wrapText = new WrapText( - cellTheme && cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute - ); + const wrapText = new WrapText(cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute); wrapText.name = 'text'; cellGroup.appendChild(wrapText); @@ -189,9 +187,7 @@ export function createCellContent( autoWrapText, lineClamp }; - const wrapText = new WrapText( - cellTheme && cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute - ); + const wrapText = new WrapText(cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute); wrapText.name = 'text'; textMark = wrapText; } else { @@ -201,7 +197,7 @@ export function createCellContent( }, (cellGroup.parent as Group)?.theme?.userTheme?.text || {} ); - if (cellTheme && cellTheme.text) { + if (cellTheme.text) { Object.assign(textOption, cellTheme.text); } textOption.textBaseline = 'middle'; @@ -407,7 +403,7 @@ export function dealWithIcon( * @param {ColumnIconOption} icon * @return {*} */ -function dealWithRichTextIcon(icon: ColumnIconOption) { +export function dealWithRichTextIcon(icon: ColumnIconOption) { // positionType在外部处理 const config = {} as any; diff --git a/packages/vtable/src/state/hover/col.ts b/packages/vtable/src/state/hover/col.ts index d5b9d4c7b..174fd0403 100644 --- a/packages/vtable/src/state/hover/col.ts +++ b/packages/vtable/src/state/hover/col.ts @@ -17,8 +17,8 @@ export function clearColHover( updateCell(scenegraph, col, row); } // 更新body - const cellGroup = scenegraph.getCell(col, table.columnHeaderLevelCount); - cellGroup?.parent.addUpdateBoundTag(); + const cellGroup = scenegraph.getColGroup(col); + cellGroup?.addUpdateBoundTag(); return true; } @@ -39,8 +39,8 @@ export function updateColHover( updateCell(scenegraph, col, row); } // 更新body - const cellGroup = scenegraph.getCell(col, table.columnHeaderLevelCount); - cellGroup?.parent.addUpdateBoundTag(); + const cellGroup = scenegraph.getColGroup(col); + cellGroup?.addUpdateBoundTag(); return true; } diff --git a/packages/vtable/src/tools/NumberMap.ts b/packages/vtable/src/tools/NumberMap.ts index 8ee7a020f..9ef03b873 100644 --- a/packages/vtable/src/tools/NumberMap.ts +++ b/packages/vtable/src/tools/NumberMap.ts @@ -127,4 +127,9 @@ export class NumberMap { } } } + clear() { + this._keys.length = 0; + this._vals = {}; + this._sorted = false; + } } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 8337bea99..e1005232a 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -515,6 +515,9 @@ export interface BaseTableAPI { resize: () => void; getMergeCellRect: (col: number, row: number) => Rect; + + getTargetColAt: (absoluteX: number) => { col: number; left: number; right: number; width: number } | null; + getTargetRowAt: (absoluteY: number) => { row: number; top: number; bottom: number; height: number } | null; //#endregion tableAPI } export interface ListTableProtected extends IBaseTableProtected { diff --git a/packages/vtable/src/ts-types/list-table/layout-map/api.ts b/packages/vtable/src/ts-types/list-table/layout-map/api.ts index 0573ede8f..2422f551f 100644 --- a/packages/vtable/src/ts-types/list-table/layout-map/api.ts +++ b/packages/vtable/src/ts-types/list-table/layout-map/api.ts @@ -115,6 +115,7 @@ export interface ColumnData extends WidthData { chartType?: string; /** 如果是绘制图表库组件的图表类型 统一图表配置chartSpec */ chartSpec?: any | ((arg0: CellInfo) => any); + chartInstance?: any; sparklineSpec?: SparklineSpec | ((arg0: CellInfo) => SparklineSpec); style: ColumnStyleOption | null | undefined; define: ColumnDefine; @@ -140,6 +141,7 @@ export interface IndicatorData extends WidthData { columnType: 'text' | 'link' | 'image' | 'video' | 'sparkline' | 'progressbar' | 'chart'; //BaseColumn; chartType?: string; chartSpec?: any | ((arg0: CustomRenderFunctionArg) => any); + chartInstance?: any; style?: ColumnStyleOption | null | undefined; define: ColumnDefine; // headerIcon?: diff --git a/rush.json b/rush.json index 6560586b0..e76a02b3a 100644 --- a/rush.json +++ b/rush.json @@ -3,7 +3,6 @@ "rushVersion": "5.94.1", "pnpmVersion": "7.32.1", "nodeSupportedVersionRange": ">=14.15.0 <15.0.0 || >=16.13.0 <17.0.0 || >=18.15.0 <19.0.0", - // "nodeSupportedVersionInstructions": "Run 'nvs use' to switch to the expected node version.", "suppressNodeLtsWarning": true, "ensureConsistentVersions": true, "projectFolderMinDepth": 2, @@ -18,38 +17,42 @@ "versionBumpCommitMessage": "Bump versions [skip ci]", "changeLogUpdateCommitMessage": "Update changelogs [skip ci]" }, - // "eventHooks": { - // "preRushInstall": [], - // "postRushInstall": [], - // "preRushBuild": [], - // "postRushBuild": [] - // }, - // "telemetryEnabled": false, - // "hotfixChangeEnabled": false, - "allowedProjectTags": ["tool", "share", "package"], + "allowedProjectTags": [ + "tool", + "share", + "package" + ], "projects": [ { "packageName": "@visactor/vtable", "projectFolder": "packages/vtable", - "tags": ["package"], + "tags": [ + "package" + ], "shouldPublish": true }, { "packageName": "@internal/bundler", "projectFolder": "tools/bundler", - "tags": ["tool"], + "tags": [ + "tool" + ], "shouldPublish": false }, { "packageName": "@internal/eslint-config", "projectFolder": "share/eslint-config", - "tags": ["share"], + "tags": [ + "share" + ], "shouldPublish": false }, { "packageName": "@internal/ts-config", "projectFolder": "share/ts-config", - "tags": ["share"], + "tags": [ + "share" + ], "shouldPublish": false } ] diff --git a/tools/bundler/src/logic/babel.config.ts b/tools/bundler/src/logic/babel.config.ts index 2bf942202..cbb6abe50 100644 --- a/tools/bundler/src/logic/babel.config.ts +++ b/tools/bundler/src/logic/babel.config.ts @@ -4,10 +4,9 @@ export type BabelPlugins = { presets: PluginItem[]; plugins: PluginItem[]; }; -export function getBabelPlugins(packageName: string, es5 = true): BabelPlugins { +export function getBabelPlugins(packageName: string): BabelPlugins { const plugins = [ require.resolve('@babel/plugin-proposal-export-default-from'), - // require.resolve('@babel/plugin-transform-runtime'), require.resolve('@babel/plugin-proposal-class-properties'), [ require.resolve('babel-plugin-import'), @@ -20,20 +19,12 @@ export function getBabelPlugins(packageName: string, es5 = true): BabelPlugins { ] ]; - if (es5) { - plugins.push(require.resolve('@babel/plugin-transform-runtime')); - } - const presets = [ require.resolve('@babel/preset-react'), - // require.resolve('@babel/preset-env'), - require.resolve('@babel/preset-typescript') + require.resolve('@babel/preset-typescript'), + [require.resolve('@babel/preset-env'), { targets: 'defaults and not IE 11' }] ]; - if (es5) { - presets.push(require.resolve('@babel/preset-env')); - } - return { presets, plugins diff --git a/tools/bundler/src/logic/rollup.config.ts b/tools/bundler/src/logic/rollup.config.ts index f71a2e142..00d97ba3e 100644 --- a/tools/bundler/src/logic/rollup.config.ts +++ b/tools/bundler/src/logic/rollup.config.ts @@ -33,8 +33,7 @@ export function getRollupOptions( entry: string, rawPackageJson: RawPackageJson, babelPlugins: BabelPlugins, - config: Config, - es5 = true + config: Config ): RollupOptions { return { input: entry, @@ -43,7 +42,7 @@ export function getRollupOptions( plugins: [ resolve(), commonjs(), - babel({ ...babelPlugins, babelHelpers: es5 ? 'runtime' : 'bundled' }), + babel({ ...babelPlugins, babelHelpers: 'bundled' }), replace({ ...config.envs, preventAssignment: true }), typescript({ tsconfig: path.resolve(projectRoot, config.tsconfig), diff --git a/tools/bundler/src/tasks/umd.ts b/tools/bundler/src/tasks/umd.ts index 0f6063c32..a45f6e421 100644 --- a/tools/bundler/src/tasks/umd.ts +++ b/tools/bundler/src/tasks/umd.ts @@ -32,8 +32,8 @@ export async function buildUmd(config: Config, projectRoot: string, rawPackageJs format: 'umd', name: config.name || packageNameToPath(rawPackageJson.name), file: minify - ? `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.es5.min.js` - : `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.es5.js`, + ? `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.min.js` + : `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.js`, exports: 'named', globals: { react: 'React', ...config.globals } } @@ -42,33 +42,4 @@ export async function buildUmd(config: Config, projectRoot: string, rawPackageJs if (bundle) { await bundle.close(); } - - // build es6 - const babelPluginsEs6 = getBabelPlugins(rawPackageJson.name, false); - const rollupOptionsEs6 = getRollupOptions( - projectRoot, - entry, - rawPackageJson, - babelPluginsEs6, - { ...config, minify }, - false - ); - DebugConfig('RollupOptionsEs6', JSON.stringify(rollupOptionsEs6)); - const bundleEs6 = await rollup(rollupOptionsEs6); - - await generateOutputs(bundleEs6, [ - { - format: 'umd', - name: config.name || packageNameToPath(rawPackageJson.name), - file: minify - ? `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.min.js` - : `${dest}/${config.umdOutputFilename || packageNameToPath(rawPackageJson.name)}.js`, - exports: 'named', - globals: { react: 'React' } - } - ]); - - if (bundleEs6) { - await bundleEs6.close(); - } }