@antv/s2
Version:
effective spreadsheet render core lib
282 lines • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.areAllFieldsEmpty = exports.getLeftLeafNode = exports.getLeafColumnsWithKey = exports.getLeafColumns = exports.getNodeRoot = exports.getCellRange = exports.splitInViewIndexesWithFrozen = exports.calculateFrozenCornerCells = exports.getFrozenGroupTypeByCell = exports.translateGroupY = exports.translateGroupX = exports.translateGroup = exports.optimizeScrollXY = exports.calculateInViewIndexes = exports.isFrozenTrailingRow = exports.isFrozenRow = exports.isFrozenTrailingCol = exports.isFrozenCol = void 0;
const lodash_1 = require("lodash");
const frozen_1 = require("../common/constant/frozen");
const pagination_1 = require("../common/constant/pagination");
const isFrozenCol = (colIndex, frozenCount) => frozenCount > 0 && colIndex < frozenCount;
exports.isFrozenCol = isFrozenCol;
const isFrozenTrailingCol = (colIndex, frozenCount, colLength) => frozenCount > 0 && colIndex >= colLength - frozenCount;
exports.isFrozenTrailingCol = isFrozenTrailingCol;
const isFrozenRow = (rowIndex, minRowIndex, frozenCount) => frozenCount > 0 && rowIndex < minRowIndex + frozenCount;
exports.isFrozenRow = isFrozenRow;
const isFrozenTrailingRow = (rowIndex, maxRowIndex, frozenCount) => frozenCount > 0 && rowIndex >= maxRowIndex + 1 - frozenCount;
exports.isFrozenTrailingRow = isFrozenTrailingRow;
/**
* 计算偏移 scrollX、scrollY 的时候,在视窗中的节点索引
*/
const calculateInViewIndexes = (options) => {
const { scrollX, scrollY, widths, heights, viewport, rowRemainWidth } = options;
// 1. 计算 x min、max
let xMin = (0, lodash_1.findIndex)(widths, (width, idx) => {
const x = scrollX - ((0, lodash_1.isNil)(rowRemainWidth) ? 0 : rowRemainWidth) + viewport.x;
return x >= width && x < widths[idx + 1];
}, 0);
xMin = Math.max(xMin, 0);
let xMax = (0, lodash_1.findIndex)(widths, (width, idx) => {
const x = viewport.width + scrollX + viewport.x;
return x >= width && x < widths[idx + 1];
}, xMin);
xMax = Math.min(xMax === -1 ? Infinity : xMax, widths.length - 2);
const { start: yMin, end: yMax } = heights.getIndexRange(scrollY + viewport.y, viewport.height + scrollY + viewport.y);
return [xMin, xMax, yMin, yMax];
};
exports.calculateInViewIndexes = calculateInViewIndexes;
/**
* 优化滚动方向,对于小角度的滚动,固定为一个方向
* @param x
* @param y
* @param ratio
*/
const optimizeScrollXY = (x, y, ratio) => {
// 调参工程师
const ANGLE = 2;
const angle = Math.abs(x / y);
// 经过滚动优化之后的 x, y
const deltaX = angle <= 1 / ANGLE ? 0 : x;
const deltaY = angle > ANGLE ? 0 : y;
return [deltaX * ratio.horizontal, deltaY * ratio.vertical];
};
exports.optimizeScrollXY = optimizeScrollXY;
const translateGroup = (group, scrollX, scrollY) => {
if (group) {
const [preX, preY] = group.getPosition();
group.translate(scrollX - preX, scrollY - preY);
}
};
exports.translateGroup = translateGroup;
const translateGroupX = (group, scrollX) => {
if (group) {
const [preX] = group.getPosition();
group.translate(scrollX - preX, 0);
}
};
exports.translateGroupX = translateGroupX;
const translateGroupY = (group, scrollY) => {
if (group) {
const [, preY] = group.getPosition();
group === null || group === void 0 ? void 0 : group.translate(0, scrollY - preY);
}
};
exports.translateGroupY = translateGroupY;
/**
* frozen frozenTrailing
* ColCount ColCount
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | frozenRow | | frozenRowCount
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | fro | | fro |
* | zen | panel | zen |
* | col | scroll | trailing |
* | | | col |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* | | frozenTrailingRow | | frozenTrailingRowCount
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* @description returns which group data cell belongs in frozen mode
*/
const getFrozenGroupTypeByCell = (meta, frozenOptions, colLength, cellRange) => {
const { colCount = 0, rowCount = 0, trailingColCount = 0, trailingRowCount = 0, } = frozenOptions;
const { colIndex, rowIndex } = meta;
if ((0, exports.isFrozenRow)(rowIndex, cellRange.start, rowCount)) {
return frozen_1.FrozenGroupType.Row;
}
if ((0, exports.isFrozenTrailingRow)(rowIndex, cellRange.end, trailingRowCount)) {
return frozen_1.FrozenGroupType.TrailingRow;
}
if ((0, exports.isFrozenCol)(colIndex, colCount)) {
return frozen_1.FrozenGroupType.Col;
}
if ((0, exports.isFrozenTrailingCol)(colIndex, trailingColCount, colLength)) {
return frozen_1.FrozenGroupType.TrailingCol;
}
return frozen_1.FrozenGroupType.Scroll;
};
exports.getFrozenGroupTypeByCell = getFrozenGroupTypeByCell;
/**
* @description calculate all cells in frozen group's intersection region
*/
const calculateFrozenCornerCells = (frozenOptions, colLength, cellRange) => {
const { colCount: frozenColCount = 0, rowCount: frozenRowCount = 0, trailingColCount: frozenTrailingColCount = 0, trailingRowCount: frozenTrailingRowCount = 0, } = frozenOptions;
const result = {
[frozen_1.FrozenGroupType.TopLeft]: [],
[frozen_1.FrozenGroupType.TopRight]: [],
[frozen_1.FrozenGroupType.BottomLeft]: [],
[frozen_1.FrozenGroupType.BottomRight]: [],
};
// frozenColGroup with frozenRowGroup or frozenTrailingRowGroup. Top left and Bottom left corner.
for (let i = 0; i < frozenColCount; i++) {
for (let j = cellRange.start; j < cellRange.start + frozenRowCount; j++) {
result[frozen_1.FrozenGroupType.TopLeft].push({
x: i,
y: j,
});
}
if (frozenTrailingRowCount > 0) {
for (let j = 0; j < frozenTrailingRowCount; j++) {
const index = cellRange.end - j;
result[frozen_1.FrozenGroupType.BottomLeft].push({
x: i,
y: index,
});
}
}
}
// frozenTrailingColGroup with frozenRowGroup or frozenTrailingRowGroup. Top right and bottom right corner.
for (let i = 0; i < frozenTrailingColCount; i++) {
const colIndex = colLength - 1 - i;
for (let j = cellRange.start; j < cellRange.start + frozenRowCount; j++) {
result[frozen_1.FrozenGroupType.TopRight].push({
x: colIndex,
y: j,
});
}
if (frozenTrailingRowCount > 0) {
for (let j = 0; j < frozenTrailingRowCount; j++) {
const index = cellRange.end - j;
result[frozen_1.FrozenGroupType.BottomRight].push({
x: colIndex,
y: index,
});
}
}
}
return result;
};
exports.calculateFrozenCornerCells = calculateFrozenCornerCells;
/**
* @description split all cells in current panel with five child group
*/
const splitInViewIndexesWithFrozen = (indexes, frozenOptions, colLength, cellRange) => {
const { colCount = 0, rowCount = 0, trailingColCount = 0, trailingRowCount = 0, } = frozenOptions;
const centerIndexes = [...indexes];
// Cut off frozen cells from centerIndexes
if ((0, exports.isFrozenCol)(centerIndexes[0], colCount)) {
centerIndexes[0] = colCount;
}
if ((0, exports.isFrozenTrailingCol)(centerIndexes[1], trailingColCount, colLength)) {
centerIndexes[1] = colLength - trailingColCount - 1;
}
if ((0, exports.isFrozenRow)(centerIndexes[2], cellRange.start, rowCount)) {
centerIndexes[2] = cellRange.start + rowCount;
}
if ((0, exports.isFrozenTrailingRow)(centerIndexes[3], cellRange.end, trailingRowCount)) {
centerIndexes[3] = cellRange.end - trailingRowCount;
}
// Calculate indexes for four frozen groups
const frozenRowIndexes = [...centerIndexes];
frozenRowIndexes[2] = cellRange.start;
frozenRowIndexes[3] = cellRange.start + rowCount - 1;
const frozenColIndexes = [...centerIndexes];
frozenColIndexes[0] = 0;
frozenColIndexes[1] = colCount - 1;
const frozenTrailingRowIndexes = [...centerIndexes];
frozenTrailingRowIndexes[2] = cellRange.end + 1 - trailingRowCount;
frozenTrailingRowIndexes[3] = cellRange.end;
const frozenTrailingColIndexes = [...centerIndexes];
frozenTrailingColIndexes[0] = colLength - trailingColCount;
frozenTrailingColIndexes[1] = colLength - 1;
return {
center: centerIndexes,
frozenRow: frozenRowIndexes,
frozenCol: frozenColIndexes,
frozenTrailingCol: frozenTrailingColIndexes,
frozenTrailingRow: frozenTrailingRowIndexes,
};
};
exports.splitInViewIndexesWithFrozen = splitInViewIndexesWithFrozen;
const getCellRange = (viewCellHeights, pagination) => {
const heights = viewCellHeights;
let start = 0;
let end = heights.getTotalLength() - 1;
if (pagination) {
const { current = pagination_1.DEFAULT_PAGE_INDEX, pageSize } = pagination;
start = Math.max((current - 1) * pageSize, 0);
end = Math.min(current * pageSize - 1, heights.getTotalLength() - 1);
}
return {
start,
end,
};
};
exports.getCellRange = getCellRange;
/**
* 明细表多级表头根据一个 node 返回其所属顶层节点
* @param node
* @returns {Node}
*/
const getNodeRoot = (node) => {
while (node.level !== 0) {
node = node.parent;
}
return node;
};
exports.getNodeRoot = getNodeRoot;
/**
* 获取 columns 的所有叶子节点
* @param columns 列配置
* @returns {Array} 叶子节点列组成的数组
*/
const getLeafColumns = (columns) => {
const leafs = [];
const recursionFn = (list) => {
list.forEach((column) => {
if (typeof column === 'string' || !column.children) {
leafs.push(column);
}
else {
recursionFn(column.children);
}
});
};
recursionFn(columns);
return leafs;
};
exports.getLeafColumns = getLeafColumns;
/**
* 获取 columns 的所有叶子节点的 key
* @param columns 列配置
* @returns {Array<string>} 叶子节点列的key组成的数组
*/
const getLeafColumnsWithKey = (columns = []) => {
const leafs = (0, exports.getLeafColumns)(columns);
return leafs.map((column) => {
if (typeof column === 'string') {
return column;
}
return column.field;
});
};
exports.getLeafColumnsWithKey = getLeafColumnsWithKey;
/**
* 获取一个 node 的最左叶子节点,找不到则返回自身
* @param node
* @returns {Node}
*/
const getLeftLeafNode = (node) => {
const firstNode = node.children[0];
if (!firstNode) {
return node;
}
return firstNode.isLeaf ? firstNode : (0, exports.getLeftLeafNode)(firstNode);
};
exports.getLeftLeafNode = getLeftLeafNode;
/**
* fields 的 rows、columns、values 值都为空时,返回 true
* @param {Fields} fields
* @return {boolean}
*/
const areAllFieldsEmpty = (fields) => {
return ((0, lodash_1.isEmpty)(fields.rows) && (0, lodash_1.isEmpty)(fields.columns) && (0, lodash_1.isEmpty)(fields.values));
};
exports.areAllFieldsEmpty = areAllFieldsEmpty;
//# sourceMappingURL=utils.js.map