优化
This commit is contained in:
@@ -56,18 +56,49 @@ export function getTableColWidths(elem: TemplateElement): number[] {
|
||||
return Array.from({ length: cols }, () => even);
|
||||
}
|
||||
|
||||
/** 内边距变化后保持行高/列宽不变,自动增大元素尺寸 */
|
||||
/** 将轨道尺寸总和调整为 targetTotal(保持相对比例,末项吸收取整误差) */
|
||||
function scaleTracksToTotal(tracks: number[], targetTotal: number, min = 0.5): number[] {
|
||||
if (tracks.length === 0) return [];
|
||||
const safeTotal = Math.max(tracks.length * min, targetTotal);
|
||||
const current = tracks.reduce((a, b) => a + b, 0);
|
||||
if (current <= 0) {
|
||||
return distributeTracks(safeTotal, tracks.length, min);
|
||||
}
|
||||
const scaled = tracks.map((t) => round1(Math.max(min, (t / current) * safeTotal)));
|
||||
const sum = scaled.reduce((a, b) => a + b, 0);
|
||||
const diff = round1(safeTotal - sum);
|
||||
if (scaled.length > 0 && diff !== 0) {
|
||||
scaled[scaled.length - 1] = round1(Math.max(min, scaled[scaled.length - 1] + diff));
|
||||
}
|
||||
return scaled;
|
||||
}
|
||||
|
||||
/** 将 inner 区域均分给 count 条轨道(末项吸收取整误差) */
|
||||
function distributeTracks(total: number, count: number, min = 0.5): number[] {
|
||||
if (count <= 0) return [];
|
||||
const safeTotal = Math.max(count * min, total);
|
||||
const even = round1(safeTotal / count);
|
||||
const tracks = Array.from({ length: count }, () => even);
|
||||
const sum = tracks.reduce((a, b) => a + b, 0);
|
||||
const diff = round1(safeTotal - sum);
|
||||
if (tracks.length > 0 && diff !== 0) {
|
||||
tracks[tracks.length - 1] = round1(Math.max(min, tracks[tracks.length - 1] + diff));
|
||||
}
|
||||
return tracks;
|
||||
}
|
||||
|
||||
/** 内边距变化后保持元素外框尺寸不变,按比例重算行高/列宽以适配新的内容区 */
|
||||
export function expandTableForPadding(elem: TemplateElement): TemplateElement {
|
||||
if (elem.type !== 'table') return elem;
|
||||
const pad = resolvePaddingMm(elem);
|
||||
const rowHeights = getTableRowHeights(elem);
|
||||
const colWidths = getTableColWidths(elem);
|
||||
const innerW = Math.max(1, elem.width - pad.left - pad.right);
|
||||
const innerH = Math.max(1, elem.height - pad.top - pad.bottom);
|
||||
return {
|
||||
...elem,
|
||||
tableRowHeights: rowHeights,
|
||||
tableColWidths: colWidths,
|
||||
height: round1(rowHeights.reduce((a, b) => a + b, 0) + pad.top + pad.bottom),
|
||||
width: round1(colWidths.reduce((a, b) => a + b, 0) + pad.left + pad.right),
|
||||
tableRowHeights: scaleTracksToTotal(getTableRowHeights(elem), innerH),
|
||||
tableColWidths: scaleTracksToTotal(getTableColWidths(elem), innerW),
|
||||
width: elem.width,
|
||||
height: elem.height,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -183,6 +214,53 @@ export function getCellRectMm(
|
||||
return { x: round1(x), y: round1(y), width: round1(width), height: round1(height) };
|
||||
}
|
||||
|
||||
/** 表格行列像素边界(累积取整,避免单元格背景/选区出现缝隙) */
|
||||
export function buildTableGridBoundariesPx(
|
||||
elem: TemplateElement,
|
||||
scale: number,
|
||||
originX = 0,
|
||||
originY = 0
|
||||
): { rowBounds: number[]; colBounds: number[] } {
|
||||
const pad = resolvePaddingMm(elem);
|
||||
const rowHeights = getTableRowHeights(elem);
|
||||
const colWidths = getTableColWidths(elem);
|
||||
|
||||
const rowBounds: number[] = [originY + Math.round(pad.top * scale)];
|
||||
for (const h of rowHeights) {
|
||||
rowBounds.push(rowBounds[rowBounds.length - 1] + Math.round(h * scale));
|
||||
}
|
||||
|
||||
const colBounds: number[] = [originX + Math.round(pad.left * scale)];
|
||||
for (const w of colWidths) {
|
||||
colBounds.push(colBounds[colBounds.length - 1] + Math.round(w * scale));
|
||||
}
|
||||
|
||||
return { rowBounds, colBounds };
|
||||
}
|
||||
|
||||
/** 单元格像素矩形,与 canvas 绘制及设计器选区 overlay 对齐 */
|
||||
export function getCellRectPx(
|
||||
elem: TemplateElement,
|
||||
row: number,
|
||||
col: number,
|
||||
scale: number,
|
||||
originX = 0,
|
||||
originY = 0
|
||||
): { x: number; y: number; width: number; height: number } {
|
||||
const { rowBounds, colBounds } = buildTableGridBoundariesPx(elem, scale, originX, originY);
|
||||
const anchor = getCellAnchor(elem, row, col);
|
||||
const { rowSpan, colSpan } = getCellSpan(elem, anchor.row, anchor.col);
|
||||
|
||||
const x = colBounds[anchor.col];
|
||||
const y = rowBounds[anchor.row];
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
width: colBounds[anchor.col + colSpan] - x,
|
||||
height: rowBounds[anchor.row + rowSpan] - y,
|
||||
};
|
||||
}
|
||||
|
||||
export function createDefaultTableElement(id: string, index: number): TemplateElement {
|
||||
const rows = 3;
|
||||
const cols = 3;
|
||||
@@ -224,28 +302,6 @@ export function resizeTableGrid(
|
||||
): TemplateElement {
|
||||
const rows = Math.max(1, Math.min(50, newRows));
|
||||
const cols = Math.max(1, Math.min(50, newCols));
|
||||
const oldRows = getTableRows(elem);
|
||||
const oldCols = getTableCols(elem);
|
||||
const { width, height } = getTableInnerSizeMm(elem);
|
||||
|
||||
let rowHeights = getTableRowHeights(elem);
|
||||
let colWidths = getTableColWidths(elem);
|
||||
|
||||
if (rows > oldRows) {
|
||||
const added = rows - oldRows;
|
||||
const avg = rowHeights.reduce((a, b) => a + b, 0) / oldRows;
|
||||
rowHeights = [...rowHeights, ...Array.from({ length: added }, () => round1(avg))];
|
||||
} else if (rows < oldRows) {
|
||||
rowHeights = rowHeights.slice(0, rows);
|
||||
}
|
||||
|
||||
if (cols > oldCols) {
|
||||
const added = cols - oldCols;
|
||||
const avg = colWidths.reduce((a, b) => a + b, 0) / oldCols;
|
||||
colWidths = [...colWidths, ...Array.from({ length: added }, () => round1(avg))];
|
||||
} else if (cols < oldCols) {
|
||||
colWidths = colWidths.slice(0, cols);
|
||||
}
|
||||
|
||||
const newCells: Record<string, TableCellData> = {};
|
||||
if (elem.tableCells) {
|
||||
@@ -259,15 +315,18 @@ export function resizeTableGrid(
|
||||
}
|
||||
|
||||
const pad = resolvePaddingMm(elem);
|
||||
const innerW = Math.max(1, elem.width - pad.left - pad.right);
|
||||
const innerH = Math.max(1, elem.height - pad.top - pad.bottom);
|
||||
|
||||
const next: TemplateElement = {
|
||||
...elem,
|
||||
tableRows: rows,
|
||||
tableCols: cols,
|
||||
tableRowHeights: rowHeights,
|
||||
tableColWidths: colWidths,
|
||||
tableRowHeights: distributeTracks(innerH, rows),
|
||||
tableColWidths: distributeTracks(innerW, cols),
|
||||
tableCells: newCells,
|
||||
width: round1(colWidths.reduce((a, b) => a + b, 0) + pad.left + pad.right),
|
||||
height: round1(rowHeights.reduce((a, b) => a + b, 0) + pad.top + pad.bottom),
|
||||
width: elem.width,
|
||||
height: elem.height,
|
||||
};
|
||||
return sanitizeTableMerges(next);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user