diff --git a/common/changes/@visactor/vtable/2758-bug-pivot-table-celltype-chart-error_2024-11-05-07-26.json b/common/changes/@visactor/vtable/2758-bug-pivot-table-celltype-chart-error_2024-11-05-07-26.json new file mode 100644 index 000000000..cfb8fb0b0 --- /dev/null +++ b/common/changes/@visactor/vtable/2758-bug-pivot-table-celltype-chart-error_2024-11-05-07-26.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: when pivot cell type set chart not data cell render error #2758\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file diff --git a/docs/assets/option/en/column/chart-column-type.md b/docs/assets/option/en/column/chart-column-type.md index 669d31391..9e93f8a45 100644 --- a/docs/assets/option/en/column/chart-column-type.md +++ b/docs/assets/option/en/column/chart-column-type.md @@ -23,3 +23,7 @@ Corresponding to the injected chart library component name **Chart type exclusive configuration options** Set the spec of the chart, or set it to a function that returns a different spec. The data displayed in the chart is provided by records. + +##${prefix} noDataRenderNothing(boolean) = false + +Do not render the chart when there is no data. Defaults to false diff --git a/docs/assets/option/en/indicator/chart-indicator-type.md b/docs/assets/option/en/indicator/chart-indicator-type.md index ff81adccf..4b0ebba0c 100644 --- a/docs/assets/option/en/indicator/chart-indicator-type.md +++ b/docs/assets/option/en/indicator/chart-indicator-type.md @@ -23,3 +23,7 @@ Set the spec of the chart, or set it to a function that returns a different spec {{ use: base-indicator-type( prefix = '##'+${prefix} ) }} + +##${prefix} noDataRenderNothing(boolean) = false + +Do not render the chart when there is no data. Defaults to false diff --git a/docs/assets/option/zh/column/chart-column-type.md b/docs/assets/option/zh/column/chart-column-type.md index 376e3ba30..25e0d8f52 100644 --- a/docs/assets/option/zh/column/chart-column-type.md +++ b/docs/assets/option/zh/column/chart-column-type.md @@ -22,4 +22,8 @@ **chart 类型专属配置项** -设置图表的 spec,或者设置成函数返回不同的spec。其中显示在图表的数据是对应在 records 中提供。 +设置图表的 spec,或者设置成函数返回不同的 spec。其中显示在图表的数据是对应在 records 中提供。 + +##${prefix} noDataRenderNothing(boolean) = false + +没有数据时不渲染图表 默认为 false diff --git a/docs/assets/option/zh/indicator/chart-indicator-type.md b/docs/assets/option/zh/indicator/chart-indicator-type.md index 3501d0fc7..f5ce5fcb8 100644 --- a/docs/assets/option/zh/indicator/chart-indicator-type.md +++ b/docs/assets/option/zh/indicator/chart-indicator-type.md @@ -18,8 +18,12 @@ **chart 类型专属配置项** -设置图表的 spec,或者设置成函数返回不同的spec。其中显示在图表的数据由 records 提供。 +设置图表的 spec,或者设置成函数返回不同的 spec。其中显示在图表的数据由 records 提供。 {{ use: base-indicator-type( prefix = '##'+${prefix} ) }} + +##${prefix} noDataRenderNothing(boolean) = false + +没有数据时不渲染图表 默认为 false diff --git a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts index ba0249342..1f54152ce 100644 --- a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts +++ b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts @@ -54,6 +54,20 @@ export function isShareChartSpec(col: number, row: number, layout: PivotHeaderLa } return true; } +export function isNoChartDataRenderNothing(col: number, row: number, layout: PivotHeaderLayoutMap): any { + const paths = layout.getCellHeaderPaths(col, row); + let indicatorObj; + if (layout.indicatorsAsCol) { + const indicatorKey = paths.colHeaderPaths.find(colPath => colPath.indicatorKey)?.indicatorKey; + indicatorObj = layout.columnObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } else { + const indicatorKey = paths.rowHeaderPaths.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + indicatorObj = layout.columnObjects.find(indicator => indicator.indicatorKey === indicatorKey); + } + const noDataRenderNothing = indicatorObj?.noDataRenderNothing; + + return noDataRenderNothing; +} /** 检查是否有直角坐标系的图表 */ export function checkHasCartesianChart(indicatorsDefine: (IIndicator | IChartIndicator | string)[]) { let isHasCartesianChart = false; diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 8bdcdaa53..81f9d4d17 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -43,6 +43,7 @@ import { getRawChartSpec, isCartesianChart, isHasCartesianChartInline, + isNoChartDataRenderNothing, isShareChartSpec } from './chart-helper/get-chart-spec'; import type { ITreeLayoutHeadNode, LayouTreeNode } from './tree-helper'; @@ -3085,7 +3086,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { getChartDataId(col: number, row: number): any { return getChartDataId(col, row, this); } - + /** 是否当chart没有数据时 图表单元格不绘制chart的任何内容 如网格线 */ + isNoChartDataRenderNothing(col: number, row: number): boolean { + return isNoChartDataRenderNothing(col, row, this); + } setPagination(pagination: IPagination): void { this.clearCellRangeMap(); this._table.internalProps.useOneRowHeightFillAll = false; diff --git a/packages/vtable/src/layout/simple-header-layout.ts b/packages/vtable/src/layout/simple-header-layout.ts index 51018758f..2f5d0531e 100644 --- a/packages/vtable/src/layout/simple-header-layout.ts +++ b/packages/vtable/src/layout/simple-header-layout.ts @@ -12,7 +12,7 @@ import type { Aggregation, IRowSeriesNumber } from '../ts-types'; -import type { ColumnsDefine, TextColumnDefine } from '../ts-types/list-table/define'; +import type { ChartColumnDefine, ColumnsDefine } from '../ts-types/list-table/define'; import type { ColumnData, ColumnDefine, @@ -1354,6 +1354,12 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { } return true; } + /** 是否当chart没有数据时 图表单元格不绘制chart的任何内容 如网格线 */ + isNoChartDataRenderNothing(col: number, row: number): boolean { + const body = this.getBody(col, row); + const noDataRenderNothing = ((body as ColumnData)?.define as ChartColumnDefine).noDataRenderNothing; + return noDataRenderNothing; + } getChartSpec(col: number, row: number) { return this.getRawChartSpec(col, row); } diff --git a/packages/vtable/src/layout/tree-helper.ts b/packages/vtable/src/layout/tree-helper.ts index 641ae4c30..28295a57c 100644 --- a/packages/vtable/src/layout/tree-helper.ts +++ b/packages/vtable/src/layout/tree-helper.ts @@ -479,6 +479,7 @@ export function dealHeader( cellType: indicatorInfo?.cellType ?? (indicatorInfo as any)?.columnType ?? 'text', chartModule: 'chartModule' in indicatorInfo ? indicatorInfo.chartModule : null, chartSpec: 'chartSpec' in indicatorInfo ? indicatorInfo.chartSpec : null, + noDataRenderNothing: 'noDataRenderNothing' in indicatorInfo ? indicatorInfo.noDataRenderNothing : false, sparklineSpec: 'sparklineSpec' in indicatorInfo ? indicatorInfo.sparklineSpec : null, style: indicatorInfo?.style, icon: indicatorInfo?.icon, @@ -668,6 +669,7 @@ export function dealHeaderForTreeMode( cellType: indicatorInfo?.cellType ?? (indicatorInfo as any)?.columnType ?? 'text', chartModule: 'chartModule' in indicatorInfo ? indicatorInfo.chartModule : null, chartSpec: 'chartSpec' in indicatorInfo ? indicatorInfo.chartSpec : null, + noDataRenderNothing: 'noDataRenderNothing' in indicatorInfo ? indicatorInfo.noDataRenderNothing : false, sparklineSpec: 'sparklineSpec' in indicatorInfo ? indicatorInfo.sparklineSpec : null, style: indicatorInfo?.style, icon: indicatorInfo?.icon, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 36e20624a..b4a3d888b 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -278,7 +278,8 @@ export function createCell( table, cellTheme, table.internalProps.layoutMap.isShareChartSpec(col, row), - isAsync + isAsync, + table.internalProps.layoutMap.isNoChartDataRenderNothing(col, row) ); } else if (type === 'progressbar') { const style = table._getCellStyle(col, row) as ProgressBarStyle; 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 dc7e548a0..f922e45d7 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 @@ -24,7 +24,8 @@ export function createChartCellGroup( table: BaseTableAPI, cellTheme: IThemeSpec, isShareChartSpec: true, - isAsync: boolean + isAsync: boolean, + isNoChartDataRenderNothing: boolean ) { // 获取注册的chart图表类型 const registerCharts = registerChartTypes.get(); @@ -86,42 +87,43 @@ export function createChartCellGroup( } cellGroup.AABBBounds.width(); // TODO 需要底层VRender修改 // chart - const chartGroup = new Chart(isShareChartSpec, { - stroke: false, - x: padding[3], - y: padding[0], - // canvas: table.canvas, - canvas: table.canvas ?? (table.scenegraph.stage.window.getContext().canvas as unknown as HTMLCanvasElement), - mode: table.options.mode, - modeParams: table.options.modeParams, - spec: chartSpec, - ClassType, - width: width - padding[3] - padding[1], - height: height - padding[2] - padding[0], - chartInstance, - dataId, - data: table.getCellValue(col, row), - cellPadding: padding, - dpr: table.internalProps.pixelRatio, - // viewBox: { - // x1: Math.ceil(cellGroup.globalAABBBounds.x1 + padding[3] + table.scrollLeft), - // x2: Math.ceil(cellGroup.globalAABBBounds.x1 + width - padding[1] + table.scrollLeft), - // y1: Math.ceil(cellGroup.globalAABBBounds.y1 + padding[0] + table.scrollTop), - // y2: Math.ceil(cellGroup.globalAABBBounds.y1 + height - padding[2] + table.scrollTop) - // }, - axes: table.isPivotChart() ? table.internalProps.layoutMap.getChartAxes(col, row) : [], - // clipRect: { - // left: cellGroup.globalAABBBounds.x1 + (table as any).tableX + padding[3], - // top: cellGroup.globalAABBBounds.y1 + (table as any).tableY + padding[0], - // width: width - padding[1] - padding[3], //cellGroup.globalAABBBounds.width() - padding[1] - padding[3], - // height: height - padding[0] - padding[2], - // }, - tableChartOption: table.options.chartOption - }); - cellGroup.appendChild(chartGroup); - // 将生成的实例存到layoutMap中 共享 - table.internalProps.layoutMap.setChartInstance(col, row, chartGroup.chartInstance); - + if ((isNoChartDataRenderNothing && Array.isArray(table.getCellValue(col, row))) || !isNoChartDataRenderNothing) { + const chartGroup = new Chart(isShareChartSpec, { + stroke: false, + x: padding[3], + y: padding[0], + // canvas: table.canvas, + canvas: table.canvas ?? (table.scenegraph.stage.window.getContext().canvas as unknown as HTMLCanvasElement), + mode: table.options.mode, + modeParams: table.options.modeParams, + spec: chartSpec, + ClassType, + width: width - padding[3] - padding[1], + height: height - padding[2] - padding[0], + chartInstance, + dataId, + data: table.getCellValue(col, row) || [], + cellPadding: padding, + dpr: table.internalProps.pixelRatio, + // viewBox: { + // x1: Math.ceil(cellGroup.globalAABBBounds.x1 + padding[3] + table.scrollLeft), + // x2: Math.ceil(cellGroup.globalAABBBounds.x1 + width - padding[1] + table.scrollLeft), + // y1: Math.ceil(cellGroup.globalAABBBounds.y1 + padding[0] + table.scrollTop), + // y2: Math.ceil(cellGroup.globalAABBBounds.y1 + height - padding[2] + table.scrollTop) + // }, + axes: table.isPivotChart() ? table.internalProps.layoutMap.getChartAxes(col, row) : [], + // clipRect: { + // left: cellGroup.globalAABBBounds.x1 + (table as any).tableX + padding[3], + // top: cellGroup.globalAABBBounds.y1 + (table as any).tableY + padding[0], + // width: width - padding[1] - padding[3], //cellGroup.globalAABBBounds.width() - padding[1] - padding[3], + // height: height - padding[0] - padding[2], + // }, + tableChartOption: table.options.chartOption + }); + cellGroup.appendChild(chartGroup); + // 将生成的实例存到layoutMap中 共享 + table.internalProps.layoutMap.setChartInstance(col, row, chartGroup.chartInstance); + } return cellGroup; } diff --git a/packages/vtable/src/ts-types/list-table/define/chart-define.ts b/packages/vtable/src/ts-types/list-table/define/chart-define.ts index 5482ccfcd..475c95b70 100644 --- a/packages/vtable/src/ts-types/list-table/define/chart-define.ts +++ b/packages/vtable/src/ts-types/list-table/define/chart-define.ts @@ -10,4 +10,5 @@ export interface IChartColumnBodyDefine extends IBasicColumnBodyDefine { chartModule?: string; /** 对应图表库的spec 其中value对应在records中提供 */ chartSpec?: any | ((arg0: CellInfo) => any); + noDataRenderNothing?: boolean; // 没有数据时不渲染图表 默认为false } 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 3d4e540ac..fa7712598 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 @@ -154,6 +154,7 @@ export interface IndicatorData extends WidthData { chartModule?: string; chartSpec?: any | ((arg0: CustomRenderFunctionArg) => any); chartInstance?: any; + noDataRenderNothing?: boolean; style?: ColumnStyleOption | null | undefined; define: ColumnDefine; // headerIcon?: diff --git a/packages/vtable/src/ts-types/pivot-table/indicator/chart-indicator.ts b/packages/vtable/src/ts-types/pivot-table/indicator/chart-indicator.ts index 932b6cbe9..4eb47a025 100644 --- a/packages/vtable/src/ts-types/pivot-table/indicator/chart-indicator.ts +++ b/packages/vtable/src/ts-types/pivot-table/indicator/chart-indicator.ts @@ -9,4 +9,5 @@ export interface IChartColumnIndicator extends IBasicColumnIndicator { chartModule?: string; // 如果是绘制图表库组件的图表类型 需要将注入的组件名称 写到chartType chartSpec?: any | ((arg0: CellInfo) => any); // 如果是绘制图表库组件的图表类型 统一图表配置chartSpec + noDataRenderNothing?: boolean; // 没有数据时不渲染图表 默认为false }