UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

462 lines 22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PivotChartFacet = void 0; const s2_1 = require("@antv/s2"); const lodash_1 = require("lodash"); const constant_1 = require("../constant"); const axis_col_1 = require("../header/axis-col"); const axis_corner_1 = require("../header/axis-corner"); const axis_row_1 = require("../header/axis-row"); const corner_1 = require("../header/corner"); const axis_col_cell_1 = require("../cell/axis-col-cell"); const axis_corner_cell_1 = require("../cell/axis-corner-cell"); const axis_row_cell_1 = require("../cell/axis-row-cell"); const cell_type_1 = require("../cell/cell-type"); const separate_axis_1 = require("../utils/separate-axis"); const corner_bbox_1 = require("./corner-bbox"); const frame_1 = require("./frame"); const panel_bbox_1 = require("./panel-bbox"); class PivotChartFacet extends s2_1.PivotFacet { constructor() { super(...arguments); /** * 获取单元格的所有子节点 (含非可视区域) * @example * const rowCell = facet.getRowCells()[0] * facet.getCellChildrenNodes(rowCell) */ this.getCellChildrenNodes = (cell) => { var _a; const selectNode = (_a = cell === null || cell === void 0 ? void 0 : cell.getMeta) === null || _a === void 0 ? void 0 : _a.call(cell); return s2_1.Node.getAllChildrenNodes(selectNode, (node) => { // 行列头区域,也把对应的 axis 区域 node 返回 return node.relatedNode ? [node, node.relatedNode] : [node]; }); }; } doLayout() { let layoutResult = this.buildAllHeaderHierarchy(); layoutResult = (0, separate_axis_1.separateRowColLeafNodes)(layoutResult, this.spreadsheet); this.calculateHeaderNodesCoordinate(layoutResult); this.calculateAxisHierarchyCoordinate(layoutResult); const { rowsHierarchy, colsHierarchy, axisRowsHierarchy, axisColsHierarchy, } = layoutResult; return { axisRowsHierarchy, axisColsHierarchy, rowsHierarchy, rowNodes: rowsHierarchy.getNodes(), rowLeafNodes: rowsHierarchy.getLeaves(), colsHierarchy, colNodes: colsHierarchy.getNodes(), colLeafNodes: colsHierarchy.getLeaves(), }; } getColLeafNodeRelatedCount(colNode) { const isValueInCols = this.spreadsheet.isValueInCols(); const isPolar = this.spreadsheet.isPolarCoordinate(); const size = !isValueInCols && !isPolar ? (0, lodash_1.get)(colNode.relatedNode, 'children', []).length : 1; return size; } getRowLeafNodeRelatedCount(rowNode) { const isValueInCols = this.spreadsheet.isValueInCols(); const isPolar = this.spreadsheet.isPolarCoordinate(); const size = isValueInCols && !isPolar ? (0, lodash_1.get)(rowNode.relatedNode, 'children', []).length : 1; return size; } getRowAxisWidth() { var _a, _b; const { rowCell } = this.spreadsheet.options.style; const { rows = [] } = this.spreadsheet.dataSet.fields; const lastRow = (0, lodash_1.last)(rows); return (0, s2_1.round)((_b = (_a = rowCell === null || rowCell === void 0 ? void 0 : rowCell.widthByField) === null || _a === void 0 ? void 0 : _a[lastRow]) !== null && _b !== void 0 ? _b : 0); } getColAxisHeight() { var _a, _b; const { colCell } = this.spreadsheet.options.style; const { columns = [] } = this.spreadsheet.dataSet.fields; const lastCol = (0, lodash_1.last)(columns); return (0, s2_1.round)((_b = (_a = colCell === null || colCell === void 0 ? void 0 : colCell.heightByField) === null || _a === void 0 ? void 0 : _a[lastCol]) !== null && _b !== void 0 ? _b : 0); } getCompactGridColNodeWidth(colNode) { const { dataCell } = this.spreadsheet.options.style; const dataCellWidth = (0, s2_1.getCellWidth)(dataCell, this.getColLeafNodeRelatedCount(colNode)); return (0, s2_1.round)(dataCellWidth); } getAdaptGridColWidth(colLeafNodes, colNode, rowHeaderWidth) { const { rows = [] } = this.spreadsheet.dataSet.fields; const { dataCell } = this.spreadsheet.options.style; const rowHeaderColSize = Math.max(0, rows.length - 1); const colHeaderColSize = (0, lodash_1.sum)(colLeafNodes.map((node) => this.getColLeafNodeRelatedCount(node))); const { width } = this.getCanvasSize(); const availableWidth = width - this.getSeriesNumberWidth() - this.getRowAxisWidth() - frame_1.Frame.getVerticalBorderWidth(this.spreadsheet); const colSize = Math.max(1, rowHeaderColSize + colHeaderColSize); const currentSize = colNode ? this.getColLeafNodeRelatedCount(colNode) : 1; if (!rowHeaderWidth) { return (0, s2_1.round)(currentSize * Math.max((0, s2_1.getCellWidth)(dataCell), (0, lodash_1.floor)(availableWidth / colSize))); } return (0, s2_1.round)(currentSize * Math.max((0, s2_1.getCellWidth)(dataCell), (0, lodash_1.floor)((availableWidth - rowHeaderWidth) / colHeaderColSize))); } getRowLeafNodeHeight(rowLeafNode) { var _a; const customHeight = this.getCustomRowCellHeight(rowLeafNode); // 1. 拖拽后的宽度优先级最高 if ((0, lodash_1.isNumber)(customHeight)) { return (0, s2_1.round)(customHeight); } const { dataCell } = this.spreadsheet.options.style; const dataCellHeight = (0, s2_1.round)((_a = dataCell === null || dataCell === void 0 ? void 0 : dataCell.height) !== null && _a !== void 0 ? _a : 0); return this.getRowLeafNodeRelatedCount(rowLeafNode) * dataCellHeight; } calculateAxisHierarchyCoordinate(layoutResult) { this.adjustTotalNodesCoordinateAfterSeparateAxisHierarchy(layoutResult); this.calculateAxisRowsHierarchyCoordinate(layoutResult); this.calculateAxisColsHierarchyCoordinate(layoutResult); } adjustTotalNodesCoordinateAfterSeparateAxisHierarchy(layoutResult) { // 最后一个维度分离出去后,再存在总计、小计分组时,会存在总计、小计格子出现空缺,因为 pivot-facet 层是按照未拆分的逻辑做的补全。 // 拆分后需要再处理一下,而且只需要针对维度拆分的部分做处理即可,指标拆分正常显示 var _a, _b; const { rowsHierarchy, colsHierarchy } = layoutResult; if (!(0, lodash_1.isEmpty)((_a = this.spreadsheet.options.totals) === null || _a === void 0 ? void 0 : _a.row) && this.spreadsheet.isValueInCols()) { const sampleNodeForLastLevel = rowsHierarchy.sampleNodeForLastLevel; const maxX = sampleNodeForLastLevel.x + sampleNodeForLastLevel.width; rowsHierarchy.getLeaves().forEach((leaf) => { const rightX = leaf.x + leaf.width; if (maxX > rightX) { leaf.width += maxX - rightX; } }); } if (!(0, lodash_1.isEmpty)((_b = this.spreadsheet.options.totals) === null || _b === void 0 ? void 0 : _b.col) && !this.spreadsheet.isValueInCols()) { const sampleNodeForLastLevel = colsHierarchy.sampleNodeForLastLevel; const maxY = sampleNodeForLastLevel.y + sampleNodeForLastLevel.height; colsHierarchy.getLeaves().forEach((leaf) => { const bottomY = leaf.y + leaf.height; if (maxY > bottomY) { leaf.height += maxY - bottomY; } }); } } calculateAxisRowsHierarchyCoordinate(layoutResult) { const { rowsHierarchy, axisRowsHierarchy } = layoutResult; if (!axisRowsHierarchy) { return; } const isValueInCols = this.spreadsheet.isValueInCols(); const isPolar = this.spreadsheet.isPolarCoordinate(); rowsHierarchy.width = rowsHierarchy.isPlaceholder && isValueInCols && !isPolar ? 0 : rowsHierarchy.width; const rowAxisWidth = this.getRowAxisWidth(); rowsHierarchy.getLeaves().forEach((leaf) => { const relatedNode = leaf.relatedNode; if (!relatedNode) { return; } relatedNode.y = leaf.y; relatedNode.width = rowAxisWidth; relatedNode.height = leaf.height; }); if (isValueInCols && isPolar) { axisRowsHierarchy.width = 0; axisRowsHierarchy.getNodes().forEach((node) => { node.width = 0; }); } else { axisRowsHierarchy.width = rowAxisWidth; } axisRowsHierarchy.height = rowsHierarchy.height; } calculateAxisColsHierarchyCoordinate(layoutResult) { const { colsHierarchy, axisColsHierarchy } = layoutResult; if (!axisColsHierarchy) { return; } const isValueInCols = this.spreadsheet.isValueInCols(); const isPolar = this.spreadsheet.isPolarCoordinate(); const colAxisHeight = this.getColAxisHeight(); colsHierarchy.getLeaves().forEach((leaf) => { const relatedNode = leaf.relatedNode; if (!relatedNode) { return; } relatedNode.x = leaf.x; relatedNode.width = leaf.width; relatedNode.height = colAxisHeight; }); axisColsHierarchy.width = colsHierarchy.width; if (!isValueInCols && isPolar) { axisColsHierarchy.height = 0; axisColsHierarchy.getNodes().forEach((node) => { node.height = 0; }); } else { axisColsHierarchy.height = colAxisHeight; } } calculateCornerBBox() { this.cornerBBox = new corner_bbox_1.CornerBBox(this, true); } calculatePanelBBox() { this.panelBBox = new panel_bbox_1.PanelBBox(this, true); } getCenterFrame() { var _a; if (!this.centerFrame) { const { viewportWidth, viewportHeight } = this.panelBBox; const cornerWidth = this.cornerBBox.width; const cornerHeight = this.cornerBBox.height; const frame = (_a = this.spreadsheet.options) === null || _a === void 0 ? void 0 : _a.frame; const frameCfg = { position: { x: this.cornerBBox.x, y: this.cornerBBox.y, }, cornerWidth, cornerHeight, viewportWidth, viewportHeight, showViewportLeftShadow: false, showViewportRightShadow: false, spreadsheet: this.spreadsheet, }; return frame ? frame(frameCfg) : new frame_1.Frame(frameCfg); } return this.centerFrame; } renderHeaders() { super.renderHeaders(); this.axisRowHeader = this.getAxisRowHeader(); if (this.axisRowHeader) { this.foregroundGroup.appendChild(this.axisRowHeader); } this.axisColumnHeader = this.getAxisColHeader(); if (this.axisColumnHeader) { this.foregroundGroup.appendChild(this.axisColumnHeader); } this.axisCornerHeader = this.getAxisCornerHeader(); if (this.axisCornerHeader) { this.foregroundGroup.appendChild(this.axisCornerHeader); } } getCornerHeader() { return (this.cornerHeader || corner_1.CornerHeader.getCornerHeader({ panelBBox: this.panelBBox, cornerBBox: this.cornerBBox, seriesNumberWidth: this.getSeriesNumberWidth(), layoutResult: this.layoutResult, spreadsheet: this.spreadsheet, })); } getAxisRowHeader() { var _a; if (this.axisRowHeader) { return this.axisRowHeader; } const { y, viewportHeight, viewportWidth, height } = this.panelBBox; const { rowsHierarchy, axisRowsHierarchy } = this.layoutResult; const seriesNumberWidth = this.getSeriesNumberWidth(); return new axis_row_1.AxisRowHeader({ width: this.cornerBBox.width, height, viewportWidth, viewportHeight, position: { x: seriesNumberWidth + rowsHierarchy.width, y }, nodes: (_a = axisRowsHierarchy === null || axisRowsHierarchy === void 0 ? void 0 : axisRowsHierarchy.getNodes()) !== null && _a !== void 0 ? _a : [], spreadsheet: this.spreadsheet, }); } getAxisColHeader() { var _a, _b; if (this.axisColumnHeader) { return this.axisColumnHeader; } const { x, width, viewportWidth, y, viewportHeight } = this.panelBBox; const { axisColsHierarchy } = this.layoutResult; return new axis_col_1.AxisColHeader({ width, cornerWidth: this.cornerBBox.width, height: (_a = axisColsHierarchy === null || axisColsHierarchy === void 0 ? void 0 : axisColsHierarchy.height) !== null && _a !== void 0 ? _a : 0, viewportWidth, viewportHeight, position: { x, y: y + viewportHeight }, nodes: (_b = axisColsHierarchy === null || axisColsHierarchy === void 0 ? void 0 : axisColsHierarchy.getNodes()) !== null && _b !== void 0 ? _b : [], spreadsheet: this.spreadsheet, }); } getAxisCornerHeader() { return (this.axisCornerHeader || axis_corner_1.AxisCornerHeader.getCornerHeader({ panelBBox: this.panelBBox, cornerBBox: this.cornerBBox, seriesNumberWidth: this.getSeriesNumberWidth(), layoutResult: this.layoutResult, spreadsheet: this.spreadsheet, })); } translateRelatedGroups(scrollX, scrollY, hRowScroll) { var _a, _b, _c; super.translateRelatedGroups(scrollX, scrollY, hRowScroll); (_a = this.axisRowHeader) === null || _a === void 0 ? void 0 : _a.onScrollXY(this.getRealScrollX(scrollX, hRowScroll), scrollY, constant_1.KEY_GROUP_ROW_AXIS_RESIZE_AREA); (_b = this.axisColumnHeader) === null || _b === void 0 ? void 0 : _b.onColScroll(scrollX, constant_1.KEY_GROUP_COL_AXIS_RESIZE_AREA); (_c = this.axisCornerHeader) === null || _c === void 0 ? void 0 : _c.onCorScroll(this.getRealScrollX(scrollX, hRowScroll)); } renderRowScrollBar(rowHeaderScrollX) { super.renderRowScrollBar(rowHeaderScrollX); if (this.hRowScrollBar) { const maxOffset = this.cornerBBox.originalWidth - this.cornerBBox.width; this.hRowScrollBar.addEventListener(s2_1.ScrollType.ScrollChange, ({ offset }) => { var _a, _b; const newOffset = this.getValidScrollBarOffset(offset, maxOffset); const newRowHeaderScrollX = (0, lodash_1.floor)(newOffset); this.setScrollOffset({ rowHeaderScrollX: newRowHeaderScrollX }); (_a = this.axisRowHeader) === null || _a === void 0 ? void 0 : _a.onRowScrollX(newRowHeaderScrollX, constant_1.KEY_GROUP_ROW_AXIS_RESIZE_AREA); (_b = this.axisCornerHeader) === null || _b === void 0 ? void 0 : _b.onRowScrollX(newRowHeaderScrollX); }); } } /** * 根据行列索引获取单元格元数据 */ getCellMeta(rowIndex = 0, colIndex = 0) { var _a, _b, _c, _d; const { options, dataSet } = this.spreadsheet; const { axisRowsHierarchy, axisColsHierarchy } = this.getLayoutResult(); const rowAxisLeafNodes = (_a = axisRowsHierarchy === null || axisRowsHierarchy === void 0 ? void 0 : axisRowsHierarchy.getLeaves()) !== null && _a !== void 0 ? _a : []; const colAxisLeafNodes = (_b = axisColsHierarchy === null || axisColsHierarchy === void 0 ? void 0 : axisColsHierarchy.getLeaves()) !== null && _b !== void 0 ? _b : []; const rowAxis = rowAxisLeafNodes[rowIndex]; const colAxis = colAxisLeafNodes[colIndex]; if (!rowAxis || !colAxis) { return null; } const data = []; const xField = rowAxis.field === s2_1.EXTRA_FIELD ? colAxis.field : rowAxis.field; const yField = rowAxis.field === s2_1.EXTRA_FIELD ? rowAxis.value : colAxis.value; for (const rowChild of rowAxis.children) { for (const colChild of colAxis.children) { const rowQuery = rowChild.query; const colQuery = colChild.query; const isTotals = rowChild.isTotals || rowChild.isTotalMeasure || colChild.isTotals || colChild.isTotalMeasure; const totalStatus = (0, s2_1.getHeaderTotalStatus)(rowChild, colChild); const dataQuery = (0, lodash_1.merge)({}, rowQuery, colQuery); const current = dataSet.getCellData({ query: dataQuery, isTotals, totalStatus, }); let xValue; let xValueShouldFormatter = true; if (rowChild.field === s2_1.EXTRA_FIELD) { xValue = colChild.value; xValueShouldFormatter = !colChild.isTotalRoot; } else { xValue = rowChild.value; xValueShouldFormatter = !rowChild.isTotalRoot; } const origin = Object.assign({ [xField]: xValue, [constant_1.X_FIELD_FORMATTER]: xValueShouldFormatter }, current === null || current === void 0 ? void 0 : current[s2_1.ORIGIN_FIELD]); data.push(origin); } } const cellMeta = { spreadsheet: this.spreadsheet, x: colAxis.x, y: rowAxis.y, width: colAxis.width, height: rowAxis.height, data, rowIndex, colIndex, rowId: rowAxis.id, colId: colAxis.id, fieldValue: data, valueField: yField, xField, yField, id: (0, s2_1.getDataCellId)(rowAxis.id, colAxis.id), }; return (_d = (_c = options.layoutCellMeta) === null || _c === void 0 ? void 0 : _c.call(options, cellMeta)) !== null && _d !== void 0 ? _d : cellMeta; } getFrozenColSplitLineSize() { var _a; const { viewportHeight, y: panelBBoxStartY } = this.panelBBox; const { axisColsHierarchy } = this.layoutResult; const height = viewportHeight + panelBBoxStartY + ((_a = axisColsHierarchy === null || axisColsHierarchy === void 0 ? void 0 : axisColsHierarchy.height) !== null && _a !== void 0 ? _a : 0); return { y: 0, height, }; } getAxisCornerCells() { var _a; const headerChildren = (((_a = this.getAxisCornerHeader()) === null || _a === void 0 ? void 0 : _a.children) || []); return (0, s2_1.getAllChildCells)(headerChildren, axis_corner_cell_1.AxisCornerCell).filter((cell) => cell.cellType === cell_type_1.AxisCellType.AXIS_CORNER_CELL); } getAxisRowCells() { var _a; const headerChildren = (((_a = this.getAxisRowHeader()) === null || _a === void 0 ? void 0 : _a.children) || []); return (0, s2_1.getAllChildCells)(headerChildren, axis_row_cell_1.AxisRowCell).filter((cell) => cell.cellType === cell_type_1.AxisCellType.AXIS_ROW_CELL); } getAxisColCells() { var _a; const headerChildren = (((_a = this.getAxisColHeader()) === null || _a === void 0 ? void 0 : _a.children) || []); return (0, s2_1.getAllChildCells)(headerChildren, axis_col_cell_1.AxisColCell).filter((cell) => cell.cellType === cell_type_1.AxisCellType.AXIS_COL_CELL); } /** * 获取表头单元格 (序号,角头,行头,列头) (不含可视区域) * @example 获取全部: facet.getHeaderCells() * @example 获取一组 facet.getHeaderCells(['root[&]浙江省[&]宁波市', 'root[&]浙江省[&]杭州市']) */ getHeaderCells(cellIds) { const headerCells = (0, lodash_1.concat)(this.getCornerCells(), this.getSeriesNumberCells(), this.getRowCells(), this.getColCells(), this.getAxisCornerCells(), this.getAxisRowCells(), this.getAxisColCells()); return this.filterCells(headerCells, cellIds); } getAxisCornerNodes() { var _a; return ((_a = this.axisCornerHeader) === null || _a === void 0 ? void 0 : _a.getNodes()) || []; } getAxisRowNodes() { var _a; return ((_a = this.axisRowHeader) === null || _a === void 0 ? void 0 : _a.getNodes()) || []; } getAxisColNodes() { var _a; return ((_a = this.axisColumnHeader) === null || _a === void 0 ? void 0 : _a.getNodes()) || []; } /** * 获取表头节点 (角头,序号,行头,列头) (含可视区域) * @example 获取全部: facet.getHeaderNodes() * @example 获取一组 facet.getHeaderNodes(['root[&]浙江省[&]宁波市', 'root[&]浙江省[&]杭州市']) */ getHeaderNodes(nodeIds) { const headerNodes = (0, lodash_1.concat)(this.getCornerNodes(), this.getSeriesNumberNodes(), this.getRowNodes(), this.getColNodes(), this.getAxisCornerNodes(), this.getAxisRowNodes(), this.getAxisColNodes()); if (!nodeIds) { return headerNodes; } return headerNodes.filter((node) => nodeIds.includes(node.id)); } } exports.PivotChartFacet = PivotChartFacet; //# sourceMappingURL=pivot-chart-facet.js.map