refactor: sizing

This commit is contained in:
hypercross 2026-03-15 10:14:14 +08:00
parent 8d8d4d004e
commit 57d2a7ed46
3 changed files with 72 additions and 15 deletions

View File

@ -5,10 +5,10 @@ import { pts2plotter } from '../../../plotcutter/plotter';
export interface PltExportData {
/** 单页满排时的 PLT 代码 */
pltCode: string;
/** A4 宽度 (mm) */
a4Width: number;
/** A4 高度 (mm) */
a4Height: number;
/** 排版区域宽度 (mm) */
frameWidth: number;
/** 排版区域高度 (mm) */
frameHeight: number;
/** 每页卡片数 */
cardsPerPage: number;
}
@ -24,8 +24,9 @@ export interface UsePlotterExportReturn {
/**
* PLT hook - HPGL
*
*
*
* PLT frameBoundsWithMargin (0,0)
*/
export function usePlotterExport(store: DeckStore): UsePlotterExportReturn {
const bleed = () => store.state.bleed || 1;
@ -52,19 +53,39 @@ export function usePlotterExport(store: DeckStore): UsePlotterExportReturn {
return null;
}
// 生成空走路径
const travelPaths = generateTravelPaths(layout.cardPaths, layout.a4Height);
// 使用 frameBoundsWithMargin 作为 PLT 的坐标系统
const frameBounds = layout.frameBoundsWithMargin;
const pltWidth = frameBounds.width;
const pltHeight = frameBounds.height;
// 生成 HPGL 代码(包含空走路径,从左上角出发并返回)
const allPaths = layout.cardPaths.map(p => p.points);
const startPoint: [number, number] = [0, layout.a4Height];
const endPoint: [number, number] = [0, layout.a4Height];
const plotterCode = pts2plotter(allPaths, layout.a4Width, layout.a4Height, 1, startPoint, endPoint);
// 将卡片路径转换为相对于 frameBoundsWithMargin 的坐标
// 原点在 frameBoundsWithMargin 的左上角
const relativePaths = layout.cardPaths.map(cardPath => {
const relativePoints = cardPath.points.map(([x, y]) => {
// 转换为相对于 frameBounds 左上角的坐标
const relativeX = x - frameBounds.x;
const relativeY = y - frameBounds.y;
// 翻转 Y 轴plotter 坐标 Y 向上SVG 坐标 Y 向下)
// 在 frameBounds 坐标系中原点在左上Y 向下为正
// 在 plotter 坐标系中原点在左下Y 向上为正
// 所以 plotterY = pltHeight - relativeY
return [relativeX, pltHeight - relativeY] as [number, number];
});
return relativePoints;
});
// 起点和终点都在 frameBoundsWithMargin 的左上角 (0, pltHeight)
// 在 plotter 坐标系中,左上角是 (0, height)
const startPoint: [number, number] = [0, pltHeight];
const endPoint: [number, number] = [0, pltHeight];
// 生成 HPGL 代码
const plotterCode = pts2plotter(relativePaths, pltWidth, pltHeight, 1, startPoint, endPoint);
return {
pltCode: plotterCode,
a4Width: layout.a4Width,
a4Height: layout.a4Height,
frameWidth: pltWidth,
frameHeight: pltHeight,
cardsPerPage: layout.cardsPerPage
};
};

View File

@ -178,7 +178,19 @@ export function calculateSinglePageLayout(options: LayoutOptions): SinglePageLay
a4Height,
cardsPerRow,
rowsPerPage,
cardsPerPage
cardsPerPage,
frameBounds: {
minX: offsetX,
minY: offsetY,
maxX: offsetX + maxGridWidth,
maxY: offsetY + maxGridHeight
},
frameBoundsWithMargin: {
x: offsetX - 1,
y: offsetY - 1,
width: maxGridWidth + 2,
height: maxGridHeight + 2
}
};
}

View File

@ -1,3 +1,23 @@
/**
*
*/
export interface Bounds {
minX: number;
minY: number;
maxX: number;
maxY: number;
}
/**
*
*/
export interface BoundsWithMargin {
x: number;
y: number;
width: number;
height: number;
}
/**
*
*/
@ -53,6 +73,10 @@ export interface SinglePageLayout {
rowsPerPage: number;
/** 每页总卡片数 */
cardsPerPage: number;
/** 排版区域边界框 */
frameBounds: Bounds;
/** 带边距的边界框(用于裁切标记) */
frameBoundsWithMargin: BoundsWithMargin;
}
/**