UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

204 lines 7.14 kB
import { isEmpty } from 'lodash'; import { CellBorderPosition, CellClipBox, } from '../../common/interface'; import { getIconTotalWidth } from './header-cell'; /** * text 和 icon 之间布局关系: * y轴: text 和 icon 高度上居中对齐 * x轴: * 1. text 和 icon 同为 left 或者 right 时,icon bbox 只需要简单放置在 left 或者 right 即可 * 2. 其他的情况,需要根据实际 text width 确定 icon bbox 开始位置 */ export const getVerticalTextPosition = (bbox, textBaseline) => { const { y, height } = bbox; switch (textBaseline) { case 'top': return y; case 'middle': return y + height / 2; default: return y + height; } }; export const getVerticalIconPosition = (iconSize, textY, textFontSize, textBaseline) => { const offset = (textFontSize - iconSize) / 2; switch (textBaseline) { case 'top': return textY + offset; case 'middle': return textY - iconSize / 2; default: return textY - offset - iconSize; } }; // 获取 text 及其跟随 icon 的位置坐标 export const getHorizontalTextIconPosition = (options) => { const { bbox, textWidth, textAlign, groupedIcons, iconStyle, isCustomRenderer = false, } = options; const { x, width } = bbox; const leftIconWidth = getIconTotalWidth(groupedIcons.left, iconStyle); const rightIconWidth = getIconTotalWidth(groupedIcons.right, iconStyle); let textX; let leftIconX; let rightIconX; switch (textAlign) { case 'left': leftIconX = x; textX = x + leftIconWidth; rightIconX = textX + textWidth + (rightIconWidth && iconStyle.margin.left); break; case 'right': textX = x + width - rightIconWidth - (isCustomRenderer ? textWidth : 0); leftIconX = textX - (isCustomRenderer ? 0 : textWidth) - leftIconWidth; rightIconX = x + width - rightIconWidth + (rightIconWidth && iconStyle.margin.left); break; default: const totalWidth = leftIconWidth + textWidth + rightIconWidth; leftIconX = x + width / 2 - totalWidth / 2; textX = leftIconX + leftIconWidth + (isCustomRenderer ? 0 : textWidth / 2); rightIconX = leftIconX + leftIconWidth + textWidth + (rightIconWidth && iconStyle.margin.left); break; } return { textX, leftIconX, rightIconX, }; }; /** * 类似 background-clip 属性: https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip * 分为三种类型: * borderBox: 整个 cell 的范围 * paddingBox: cell 去除 border 的范围 * contentBox: cell 去除 (border + padding) 的范围 * ------------------------------- * |b| padding | * |o| |---------------------| | * |r| | | | * |d| | | | * |e| |---------------------| | * |r| padding | * ------------------------------- * -------border-bottom----------- * ------------------------------- */ export const getCellBoxByType = (bbox, borderPositions, cellStyle, boxType) => { if (boxType === CellClipBox.BORDER_BOX) { return bbox; } let { x, y, width, height } = bbox; const { padding, horizontalBorderWidth = 0, verticalBorderWidth = 0, } = cellStyle; borderPositions.forEach((position) => { const borderWidth = [ CellBorderPosition.BOTTOM, CellBorderPosition.TOP, ].includes(position) ? horizontalBorderWidth : verticalBorderWidth; switch (position) { case CellBorderPosition.TOP: y += borderWidth; height -= borderWidth; break; case CellBorderPosition.BOTTOM: height -= borderWidth; break; case CellBorderPosition.LEFT: x += borderWidth; width -= borderWidth; break; default: width -= borderWidth; break; } }); if (boxType === CellClipBox.CONTENT_BOX) { x += padding === null || padding === void 0 ? void 0 : padding.left; y += padding === null || padding === void 0 ? void 0 : padding.top; width -= (padding === null || padding === void 0 ? void 0 : padding.left) + (padding === null || padding === void 0 ? void 0 : padding.right); height -= (padding === null || padding === void 0 ? void 0 : padding.top) + (padding === null || padding === void 0 ? void 0 : padding.bottom); } return { x, y, width, height, }; }; export const getBorderPositionAndStyle = (position, bbox, style) => { const { x, y, width, height } = bbox || {}; const { horizontalBorderWidth = 0, horizontalBorderColorOpacity, horizontalBorderColor, verticalBorderWidth = 0, verticalBorderColor, verticalBorderColorOpacity, borderDash, } = style || {}; // 如果是空数组 G 底层绘制会报错 const lineDash = isEmpty(borderDash) ? '' : borderDash; const borderStyle = [ CellBorderPosition.TOP, CellBorderPosition.BOTTOM, ].includes(position) ? { lineWidth: horizontalBorderWidth, stroke: horizontalBorderColor, strokeOpacity: horizontalBorderColorOpacity, lineDash, } : { lineWidth: verticalBorderWidth, stroke: verticalBorderColor, strokeOpacity: verticalBorderColorOpacity, lineDash, }; let x1 = 0; let y1 = 0; let x2 = 0; let y2 = 0; // horizontal if (position === CellBorderPosition.TOP || position === CellBorderPosition.BOTTOM) { let yPosition = y; if (position === CellBorderPosition.TOP) { // 完全绘制在 Cell 内,否则会导致 Border 粗细不一: https://github.com/antvis/S2/issues/426 yPosition = y + horizontalBorderWidth / 2; } else { yPosition = y + height - horizontalBorderWidth / 2; } y1 = yPosition; y2 = yPosition; x1 = x; x2 = x + width; } // vertical if (position === CellBorderPosition.LEFT || position === CellBorderPosition.RIGHT) { let xPosition = x; if (position === CellBorderPosition.LEFT) { xPosition = x + verticalBorderWidth / 2; } else { xPosition = x + width - verticalBorderWidth / 2; } x1 = xPosition; x2 = xPosition; y1 = y; y2 = y + height; } return { position: { x1, x2, y1, y2, }, style: borderStyle, }; }; //# sourceMappingURL=cell.js.map