UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

523 lines 25.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FrozenFacet = void 0; const g_1 = require("@antv/g"); const lodash_1 = require("lodash"); const constant_1 = require("../common/constant"); const frozen_group_1 = require("../group/frozen-group"); const utils_1 = require("../utils"); const grid_1 = require("../utils/grid"); const math_1 = require("../utils/math"); const base_facet_1 = require("./base-facet"); const util_1 = require("./header/util"); const utils_2 = require("./utils"); /** * Defines the row freeze abstract standard interface */ class FrozenFacet extends base_facet_1.BaseFacet { constructor() { super(...arguments); this.frozenGroupAreas = { [constant_1.FrozenGroupArea.Col]: { width: 0, x: 0, range: [], }, [constant_1.FrozenGroupArea.TrailingCol]: { width: 0, x: 0, range: [], }, [constant_1.FrozenGroupArea.Row]: { height: 0, y: 0, range: [], }, [constant_1.FrozenGroupArea.TrailingRow]: { height: 0, y: 0, range: [], }, }; this.panelScrollGroupIndexes = [0, 0, 0, 0]; this.addDataCell = (cell) => { const colLeafLength = this.getColLeafNodes().length; const cellRange = this.getCellRange(); const frozenGroupType = (0, utils_2.getFrozenGroupTypeByCell)(cell.getMeta(), this.getFrozenOptions(), colLeafLength, cellRange); if (frozenGroupType === constant_1.FrozenGroupType.Scroll) { if (cell.parentElement !== this.panelScrollGroup) { this.panelScrollGroup.appendChild(cell); } } else if (cell.parentElement !== this.frozenGroups[frozenGroupType]) { this.frozenGroups[frozenGroupType].appendChild(cell); } (0, utils_1.waitForCellMounted)(() => { this.spreadsheet.emit(constant_1.S2Event.DATA_CELL_RENDER, cell); this.spreadsheet.emit(constant_1.S2Event.LAYOUT_CELL_RENDER, cell); }); }; this.addFrozenCell = (colIndex, rowIndex, group) => { const viewMeta = this.getCellMeta(rowIndex, colIndex); if (viewMeta) { viewMeta['isFrozenCorner'] = true; const cell = this.createDataCell(viewMeta); group.appendChild(cell); } }; this.translateFrozenGroups = () => { const { scrollY, scrollX } = this.getScrollOffset(); const paginationScrollY = this.getPaginationScrollY(); const { x, y, viewportWidth, viewportHeight } = this.panelBBox; const colOffset = (0, util_1.getFrozenColOffset)(this, this.cornerBBox.width, scrollX); const trailingColOffset = (0, util_1.getFrozenTrailingColOffset)(this, viewportWidth); const trailingRowOffset = (0, util_1.getFrozenTrailingRowOffset)(this, viewportHeight, paginationScrollY); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.TopLeft], x - colOffset, y - paginationScrollY); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.TopRight], x - trailingColOffset, y - paginationScrollY); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.BottomLeft], x - colOffset, y - trailingRowOffset); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.BottomRight], x - trailingColOffset, y - trailingRowOffset); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.Row], x - scrollX, y - paginationScrollY); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.TrailingRow], x - scrollX, y - trailingRowOffset); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.Col], x - colOffset, y - scrollY - paginationScrollY); (0, utils_2.translateGroup)(this.frozenGroups[constant_1.FrozenGroupType.TrailingCol], x - trailingColOffset, y - scrollY - paginationScrollY); }; // eslint-disable-next-line max-lines-per-function this.renderFrozenGroupSplitLine = (scrollX, scrollY) => { var _a; // 在分页条件下需要额外处理 Y 轴滚动值 const relativeScrollY = Math.floor(scrollY - this.getPaginationScrollY()); // remove previous split line group (_a = this.foregroundGroup.getElementById(constant_1.KEY_GROUP_FROZEN_SPLIT_LINE)) === null || _a === void 0 ? void 0 : _a.remove(); const { splitLine } = this.spreadsheet.theme; const splitLineGroup = this.foregroundGroup.appendChild(new g_1.Group({ id: constant_1.KEY_GROUP_FROZEN_SPLIT_LINE, style: { zIndex: constant_1.FRONT_GROUND_GROUP_FROZEN_Z_INDEX, }, })); const verticalBorderStyle = { lineWidth: constant_1.SPLIT_LINE_WIDTH, stroke: splitLine === null || splitLine === void 0 ? void 0 : splitLine.verticalBorderColor, opacity: splitLine === null || splitLine === void 0 ? void 0 : splitLine.verticalBorderColorOpacity, }; const horizontalBorderStyle = { lineWidth: constant_1.SPLIT_LINE_WIDTH, stroke: splitLine === null || splitLine === void 0 ? void 0 : splitLine.horizontalBorderColor, opacity: splitLine === null || splitLine === void 0 ? void 0 : splitLine.horizontalBorderColorOpacity, }; this.renderFrozenColSplitLine(splitLineGroup, splitLine, verticalBorderStyle, scrollX); this.renderFrozenTrailingColSplitLine(splitLineGroup, splitLine, verticalBorderStyle, scrollX); this.renderFrozenRowSplitLine(splitLineGroup, splitLine, horizontalBorderStyle, relativeScrollY); this.renderFrozenTrailingRowSplitLine(splitLineGroup, splitLine, horizontalBorderStyle, relativeScrollY); }; this.renderFrozenPanelCornerGroup = () => { const cellRange = this.getCellRange(); const result = (0, utils_2.calculateFrozenCornerCells)(this.getFrozenOptions(), this.getColLeafNodes().length, cellRange); Object.keys(result || {}).forEach((key) => { const cells = result[key]; const group = this.frozenGroups[key]; if (group) { cells.forEach((cell) => { this.addFrozenCell(cell.x, cell.y, group); }); } }); }; this.getTotalHeightForRange = (start, end) => { if (start < 0 || end < 0) { return 0; } if (this.rowOffsets) { return this.rowOffsets[end + 1] - this.rowOffsets[start]; } let totalHeight = 0; for (let index = start; index < end + 1; index++) { const height = this.getDefaultCellHeight(); totalHeight += height; } return totalHeight; }; this.getShadowFill = (angle) => { var _a, _b; const { splitLine } = this.spreadsheet.theme; return `l (${angle}) 0:${(_a = splitLine === null || splitLine === void 0 ? void 0 : splitLine.shadowColors) === null || _a === void 0 ? void 0 : _a.left} 1:${(_b = splitLine === null || splitLine === void 0 ? void 0 : splitLine.shadowColors) === null || _b === void 0 ? void 0 : _b.right}`; }; } initPanelGroups() { super.initPanelGroups(); /* init frozen groups */ this.frozenGroups = [ constant_1.FrozenGroupType.Row, constant_1.FrozenGroupType.Col, constant_1.FrozenGroupType.TrailingRow, constant_1.FrozenGroupType.TrailingCol, constant_1.FrozenGroupType.TopLeft, constant_1.FrozenGroupType.TopRight, constant_1.FrozenGroupType.BottomLeft, constant_1.FrozenGroupType.BottomRight, ].reduce((acc, name) => { const frozenGroup = new frozen_group_1.FrozenGroup({ name, zIndex: constant_1.PANEL_GROUP_FROZEN_GROUP_Z_INDEX, s2: this.spreadsheet, }); this.panelGroup.appendChild(frozenGroup); acc[name] = frozenGroup; return acc; }, {}); } /** * 获取冻结数量结果,主要是针对 col top level 的结果 */ getFrozenOptions() { if (!this.validFrozenOptions) { const colLength = this.getColLeafNodes().length; const cellRange = this.getCellRange(); this.validFrozenOptions = (0, utils_1.getValidFrozenOptions)(this.spreadsheet.options.frozen, colLength, cellRange.end - cellRange.start + 1); } return this.validFrozenOptions; } calculateFrozenGroupInfo() { const { colCount, rowCount, trailingColCount, trailingRowCount } = this.getFrozenOptions(); const viewCellHeights = this.viewCellHeights; const cellRange = this.getCellRange(); const leafColNodes = this.getColLeafNodes(); if (colCount > 0) { this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].width = leafColNodes[colCount - 1].x + leafColNodes[colCount - 1].width; this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].x = 0; this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].range = [0, colCount - 1]; } if (rowCount > 0) { this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height = viewCellHeights.getCellOffsetY(cellRange.start + rowCount) - viewCellHeights.getCellOffsetY(cellRange.start); this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].y = viewCellHeights.getCellOffsetY(cellRange.start); this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].range = [ cellRange.start, cellRange.start + rowCount - 1, ]; } if (trailingColCount > 0) { this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].width = leafColNodes[leafColNodes.length - 1].x - leafColNodes[leafColNodes.length - trailingColCount].x + leafColNodes[leafColNodes.length - 1].width; this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].x = leafColNodes[leafColNodes.length - trailingColCount].x; this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].range = [ leafColNodes.length - trailingColCount, leafColNodes.length - 1, ]; } if (trailingRowCount > 0) { this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].height = viewCellHeights.getCellOffsetY(cellRange.end + 1) - viewCellHeights.getCellOffsetY(cellRange.end + 1 - trailingRowCount); this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].y = viewCellHeights.getCellOffsetY(cellRange.end + 1 - trailingRowCount); this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].range = [ cellRange.end - trailingRowCount + 1, cellRange.end, ]; } } getFinalViewport() { const { viewportHeight: height, viewportWidth: width } = this.panelBBox; const { colCount, rowCount, trailingColCount, trailingRowCount } = this.getFrozenOptions(); const finalViewport = { width, height, x: 0, y: 0, }; if (colCount > 0 || trailingColCount > 0) { finalViewport.width -= this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].width + this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].width; finalViewport.x += this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].width; } if (rowCount > 0 || trailingRowCount > 0) { // canvas 高度小于 row height 和 trailingRow height 的时候 height 为 0 if (finalViewport.height < this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height + this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].height) { finalViewport.height = 0; finalViewport.y = 0; } else { finalViewport.height -= this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height + this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].height; finalViewport.y += this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height; } } return finalViewport; } calculateXYIndexes(scrollX, scrollY) { var _a, _b; const finalViewport = this.getFinalViewport(); const indexes = this.spreadsheet.isTableMode() && ((_b = (_a = this.spreadsheet.dataSet) === null || _a === void 0 ? void 0 : _a.isEmpty) === null || _b === void 0 ? void 0 : _b.call(_a)) ? this.spreadsheet.dataSet.getEmptyViewIndexes() : (0, utils_2.calculateInViewIndexes)({ scrollX, scrollY, widths: this.viewCellWidths, heights: this.viewCellHeights, viewport: finalViewport, rowRemainWidth: this.getRealScrollX(this.cornerBBox.width), }); this.panelScrollGroupIndexes = indexes; const colLength = this.getColLeafNodes().length; const cellRange = this.getCellRange(); return (0, utils_2.splitInViewIndexesWithFrozen)(indexes, this.getFrozenOptions(), colLength, cellRange); } updateFrozenGroupGrid() { [ constant_1.FrozenGroupArea.Col, constant_1.FrozenGroupArea.Row, constant_1.FrozenGroupArea.TrailingCol, constant_1.FrozenGroupArea.TrailingRow, ].forEach((key) => { if (!this.frozenGroupAreas[key].range) { return; } let cols = []; let rows = []; if (key.toLowerCase().includes('row')) { const [rowMin, rowMax] = this.frozenGroupAreas[key].range || []; cols = this.gridInfo.cols; rows = (0, grid_1.getRowsForGrid)(rowMin, rowMax, this.viewCellHeights); if (key === constant_1.FrozenGroupArea.TrailingRow) { const top = this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].y; rows = (0, grid_1.getFrozenRowsForGrid)(rowMin, rowMax, top, this.viewCellHeights); } } else { const [colMin, colMax] = this.frozenGroupAreas[key].range || []; const nodes = this.getColLeafNodes(); cols = (0, grid_1.getColsForGrid)(colMin, colMax, nodes); rows = this.gridInfo.rows; } const frozenGroup = constant_1.FrozenGroupAreaTypeMap[key]; this.frozenGroups[frozenGroup].updateGrid({ cols, rows, }, frozenGroup); }); } updatePanelScrollGroup() { super.updatePanelScrollGroup(); this.updateFrozenGroupGrid(); } translateRelatedGroups(scrollX, scrollY, hRowScroll) { super.translateRelatedGroups(scrollX, scrollY, hRowScroll); this.translateFrozenGroups(); this.renderRowResizeArea(); this.renderFrozenGroupSplitLine(scrollX, scrollY); } renderRowResizeArea() { } getFrozenColSplitLineSize() { const { viewportHeight, y: panelBBoxStartY } = this.panelBBox; const height = viewportHeight + panelBBoxStartY; return { y: 0, height, }; } renderFrozenColSplitLine(splitLineGroup, splitLine, verticalBorderStyle, scrollX) { const { colCount } = this.getFrozenOptions(); const { x: panelBBoxStartX } = this.panelBBox; if (colCount > 0) { const cornerWidth = this.cornerBBox.width; const colOffset = (0, util_1.getFrozenColOffset)(this, cornerWidth, scrollX); const x = panelBBoxStartX + this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].width - colOffset; const { y, height } = this.getFrozenColSplitLineSize(); (0, utils_1.renderLine)(splitLineGroup, Object.assign(Object.assign({}, verticalBorderStyle), { x1: x, x2: x, y1: y, y2: y + height })); if ((splitLine === null || splitLine === void 0 ? void 0 : splitLine.showShadow) && scrollX > 0 && (this.spreadsheet.isFrozenRowHeader() || colOffset >= cornerWidth)) { splitLineGroup.appendChild(new g_1.Rect({ style: { x, y, width: splitLine === null || splitLine === void 0 ? void 0 : splitLine.shadowWidth, height, fill: this.getShadowFill(0), }, })); } } } renderFrozenTrailingColSplitLine(splitLineGroup, splitLine, verticalBorderStyle, scrollX) { const { trailingColCount } = this.getFrozenOptions(); const { viewportWidth, x: panelBBoxStartX } = this.panelBBox; if (trailingColCount > 0) { const x = viewportWidth - this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].width + panelBBoxStartX; const { y, height } = this.getFrozenColSplitLineSize(); const maxScrollX = Math.max(0, (0, lodash_1.last)(this.viewCellWidths) - viewportWidth); (0, utils_1.renderLine)(splitLineGroup, Object.assign(Object.assign({}, verticalBorderStyle), { x1: x, x2: x, y1: y, y2: y + height })); if ((splitLine === null || splitLine === void 0 ? void 0 : splitLine.showShadow) && (0, math_1.floor)(scrollX) < (0, math_1.floor)(maxScrollX)) { splitLineGroup.appendChild(new g_1.Rect({ style: { x: x - splitLine.shadowWidth, y, width: splitLine.shadowWidth, height, fill: this.getShadowFill(180), }, })); } } } getFrozenRowSplitLineSize() { const { viewportWidth, x: panelBBoxStartX } = this.panelBBox; const width = panelBBoxStartX + viewportWidth; return { x: 0, width, }; } renderFrozenRowSplitLine(splitLineGroup, splitLine, horizontalBorderStyle, scrollY) { const { rowCount } = this.getFrozenOptions(); const { y: panelBBoxStartY } = this.panelBBox; if (rowCount > 0) { const y = panelBBoxStartY + this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height; const { x, width } = this.getFrozenRowSplitLineSize(); (0, utils_1.renderLine)(splitLineGroup, Object.assign(Object.assign({}, horizontalBorderStyle), { x1: x, x2: x + width, y1: y, y2: y })); if ((splitLine === null || splitLine === void 0 ? void 0 : splitLine.showShadow) && scrollY > 0) { splitLineGroup.appendChild(new g_1.Rect({ style: { x, y, width, height: splitLine === null || splitLine === void 0 ? void 0 : splitLine.shadowWidth, fill: this.getShadowFill(90), }, })); } } } renderFrozenTrailingRowSplitLine(splitLineGroup, splitLine, horizontalBorderStyle, scrollY) { const { trailingRowCount } = this.getFrozenOptions(); const { viewportHeight } = this.panelBBox; if (trailingRowCount > 0) { const y = this.panelBBox.maxY - this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].height; const { x, width } = this.getFrozenRowSplitLineSize(); const cellRange = this.getCellRange(); // scroll boundary const maxScrollY = Math.max(0, this.viewCellHeights.getCellOffsetY(cellRange.end + 1) - this.viewCellHeights.getCellOffsetY(cellRange.start) - viewportHeight); (0, utils_1.renderLine)(splitLineGroup, Object.assign(Object.assign({}, horizontalBorderStyle), { x1: x, x2: x + width, y1: y, y2: y })); if ((splitLine === null || splitLine === void 0 ? void 0 : splitLine.showShadow) && scrollY < (0, math_1.floor)(maxScrollY)) { splitLineGroup.appendChild(new g_1.Rect({ style: { x, y: y - splitLine.shadowWidth, width, height: splitLine.shadowWidth, fill: this.getShadowFill(270), }, })); } } } render() { if (!this.shouldRender()) { return; } this.calculateFrozenGroupInfo(); this.renderFrozenPanelCornerGroup(); super.render(); } getCenterFrameScrollX(scrollX) { if (this.getFrozenOptions().colCount > 0) { return (0, util_1.getFrozenColOffset)(this, this.cornerBBox.width, scrollX); } return super.getCenterFrameScrollX(scrollX); } getDefaultCellHeight() { var _a; return (_a = this.getRowCellHeight(null)) !== null && _a !== void 0 ? _a : 0; } createOrUpdate(propertyPath, style) { utils_1.createOrUpdateRect.call(this, propertyPath, style); } clip() { const { colCount, rowCount, trailingColCount, trailingRowCount } = this.getFrozenOptions(); const { scrollX } = this.getScrollOffset(); const { x: panelScrollGroupClipX, width: panelScrollGroupClipWidth } = (0, util_1.getScrollGroupClip)(this, this.panelBBox); const frozenColGroupWidth = this.frozenGroupAreas[constant_1.FrozenGroupArea.Col].width; const frozenTrailingColWidth = this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingCol].width; const frozenRowGroupHeight = this.frozenGroupAreas[constant_1.FrozenGroupArea.Row].height; const frozenTrailingRowHeight = this.frozenGroupAreas[constant_1.FrozenGroupArea.TrailingRow].height; const panelScrollGroupClipY = this.panelBBox.y + frozenRowGroupHeight; const panelScrollGroupClipHeight = this.panelBBox.viewportHeight - frozenRowGroupHeight - frozenTrailingRowHeight; this.createOrUpdate('panelScrollGroup.style.clipPath', { x: panelScrollGroupClipX, y: panelScrollGroupClipY, width: panelScrollGroupClipWidth, height: panelScrollGroupClipHeight, }); if (colCount > 0) { this.createOrUpdate(`frozenGroups.${constant_1.FrozenGroupType.Col}.style.clipPath`, { x: this.panelBBox.x - (0, util_1.getFrozenColOffset)(this, this.cornerBBox.width, scrollX), y: panelScrollGroupClipY, width: frozenColGroupWidth, height: panelScrollGroupClipHeight, }); } else { this.frozenGroups[constant_1.FrozenGroupType.Col].style.clipPath = null; } if (trailingColCount > 0) { this.createOrUpdate(`frozenGroups.${constant_1.FrozenGroupType.TrailingCol}.style.clipPath`, { x: this.panelBBox.x + this.panelBBox.viewportWidth - frozenTrailingColWidth, y: panelScrollGroupClipY, width: frozenTrailingColWidth, height: panelScrollGroupClipHeight, }); } else { this.frozenGroups[constant_1.FrozenGroupType.TrailingCol].style.clipPath = null; } if (rowCount > 0) { this.createOrUpdate(`frozenGroups.${constant_1.FrozenGroupType.Row}.style.clipPath`, { x: panelScrollGroupClipX, y: this.panelBBox.y, width: panelScrollGroupClipWidth, height: frozenRowGroupHeight, }); } else { this.frozenGroups[constant_1.FrozenGroupType.Row].style.clipPath = null; } if (trailingRowCount > 0) { this.createOrUpdate(`frozenGroups.${constant_1.FrozenGroupType.TrailingRow}.style.clipPath`, { x: panelScrollGroupClipX, y: this.panelBBox.y + this.panelBBox.viewportHeight - frozenTrailingRowHeight, width: panelScrollGroupClipWidth, height: frozenTrailingRowHeight, }); } else { this.frozenGroups[constant_1.FrozenGroupType.TrailingRow].style.clipPath = null; } } } exports.FrozenFacet = FrozenFacet; //# sourceMappingURL=frozen-facet.js.map