feat(图表): 透视表自适应模式自动填满图表 #13402

This commit is contained in:
wisonic
2025-03-10 23:32:48 +08:00
committed by wisonic-s
parent f1cd54f360
commit e636117dc5

View File

@@ -13,7 +13,8 @@ import {
TotalStatus,
Aggregation,
S2DataConfig,
MergedCell
MergedCell,
LayoutResult
} from '@antv/s2'
import { formatterItem, valueFormatter } from '../../../formatter'
import { hexColorToRGBA, isAlphaColor, parseJson } from '../../../util'
@@ -327,6 +328,128 @@ export class TablePivot extends S2ChartView<PivotSheet> {
this.configTooltip(chart, s2Options)
// 开始渲染
const s2 = new PivotSheet(containerDom, s2DataConfig, s2Options as unknown as S2Options)
// 自适应铺满
if (basicStyle.tableColumnMode === 'adapt') {
s2.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => {
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
})
// 平铺模式行头resize
s2.on(S2Event.LAYOUT_RESIZE_ROW_WIDTH, () => {
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
})
// 树形模式行头resize
s2.on(S2Event.LAYOUT_RESIZE_TREE_WIDTH, () => {
s2.store.set('lastLayoutResult', s2.facet.layoutResult)
})
s2.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev: LayoutResult) => {
const lastLayoutResult = s2.store.get('lastLayoutResult') as LayoutResult
if (lastLayoutResult) {
// 拖动 col 表头 resize
const colWidthByFieldValue = s2.options.style?.colCfg?.widthByFieldValue
// 平铺模式拖动 row 表头 resize
const rowWidthByField = s2.options.style?.rowCfg?.widthByField
// 树形模式拖动 row 表头 resize
const treeRowWidth =
s2.options.style?.treeRowsWidth || lastLayoutResult.rowsHierarchy.width
const colWidthMap =
lastLayoutResult.colLeafNodes.reduce((p, n) => {
p[n.id] = colWidthByFieldValue?.[n.value] ?? n.width
return p
}, {}) || {}
const totalColWidth = ev.colLeafNodes.reduce((p, n) => {
n.width = colWidthMap[n.id] || n.width
n.x = p
return p + n.width
}, 0)
ev.colNodes.forEach(n => {
if (n.isLeaf) {
return
}
n.width = this.getColWidth(n)
n.x = this.getLeftChild(n).x
})
if (basicStyle.tableLayoutMode === 'tree') {
ev.rowNodes.forEach(n => {
n.width = treeRowWidth
})
ev.rowsHierarchy.width = treeRowWidth
ev.colsHierarchy.width = totalColWidth
} else {
const rowWidthMap =
lastLayoutResult.rowNodes.reduce((p, n) => {
p[n.id] = rowWidthByField?.[n.field] ?? n.width
return p
}, {}) || {}
ev.rowNodes.forEach(n => {
n.x = 0
n.width = rowWidthMap[n.id] || n.width
let tmp = n
while (tmp.parent.id !== 'root') {
n.x += tmp.parent.width
tmp = tmp.parent
}
})
const totlaRowWidth = ev.rowsHierarchy.sampleNodesForAllLevels.reduce((p, n) => {
return p + n.width
}, 0)
const maxRowLevel = ev.rowsHierarchy.maxLevel
ev.rowNodes.forEach(n => {
// 总计和中间层级的小计需要重新计算宽度
if (n.isTotalRoot || (n.isSubTotals && n.level < maxRowLevel)) {
let width = 0
for (let i = n.level; i <= maxRowLevel; i++) {
width += ev.rowsHierarchy.sampleNodesForAllLevels[i].width
}
n.width = width
}
})
ev.rowsHierarchy.width = totlaRowWidth
ev.colsHierarchy.width = totalColWidth
}
s2.store.set('lastLayoutResult', undefined)
return
}
const containerWidth = containerDom.getBoundingClientRect().width
const scale = containerWidth / (ev.colsHierarchy.width + ev.rowsHierarchy.width)
if (scale <= 1) {
return
}
const totalRowWidth = Math.round(ev.rowsHierarchy.width * scale)
ev.rowNodes.forEach(n => {
n.width = Math.round(n.width * scale)
})
if (basicStyle.tableLayoutMode !== 'tree') {
ev.rowNodes.forEach(n => {
n.x = 0
let tmp = n
while (tmp.parent.id !== 'root') {
n.x += tmp.parent.width
tmp = tmp.parent
}
})
}
let totalColWidth = ev.colLeafNodes.reduce((p, n) => {
n.width = Math.round(n.width * scale)
n.x = p
return p + n.width
}, 0)
ev.colNodes.forEach(n => {
if (n.isLeaf) {
return
}
n.width = this.getColWidth(n)
n.x = this.getLeftChild(n).x
})
const totalWidth = totalColWidth + totalRowWidth
if (totalWidth > containerWidth) {
// 从最后一列减掉
ev.colLeafNodes[ev.colLeafNodes.length - 1].width -= totalWidth - containerWidth
totalColWidth = totalColWidth - (totalWidth - containerWidth)
}
ev.colsHierarchy.width = totalColWidth
ev.rowsHierarchy.width = totalRowWidth
})
}
// tooltip
const { show } = tooltip
if (show) {
@@ -350,6 +473,23 @@ export class TablePivot extends S2ChartView<PivotSheet> {
return s2
}
private getColWidth(node) {
let width = 0
if (node.children?.length) {
node.children.forEach(child => {
width += this.getColWidth(child)
})
} else {
width = node.width
}
return width
}
private getLeftChild(node) {
if (!node.children?.length) {
return node
}
return this.getLeftChild(node.children[0])
}
private dataCellClickAction(chart: Chart, ev, s2Instance: PivotSheet, callback) {
const cell = s2Instance.getCell(ev.target)
const meta = cell.getMeta()