refactor: preview contour correctly
This commit is contained in:
parent
ee2fa057f6
commit
2b1dbd41e1
|
|
@ -19,7 +19,11 @@ export function CardPreview(props: CardPreviewProps) {
|
||||||
const selectionStyle = createMemo(() =>
|
const selectionStyle = createMemo(() =>
|
||||||
getSelectionBoxStyle(store.state.selectStart, store.state.selectEnd, store.state.dimensions)
|
getSelectionBoxStyle(store.state.selectStart, store.state.selectEnd, store.state.dimensions)
|
||||||
);
|
);
|
||||||
const shapeClipPath = createMemo(() => getShapeClipPath(store.state.shape));
|
const shapeClipPath = createMemo(() => {
|
||||||
|
const dims = store.state.dimensions;
|
||||||
|
if (!dims) return 'none';
|
||||||
|
return getShapeClipPath(store.state.shape, dims.cardWidth, dims.cardHeight, store.state.cornerRadius);
|
||||||
|
});
|
||||||
|
|
||||||
const selection = useCardSelection(store);
|
const selection = useCardSelection(store);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ export function PrintPreview(props: PrintPreviewProps) {
|
||||||
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
||||||
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
||||||
const clipPathId = `clip-${page.pageIndex}-${card.data.id || card.x}-${card.y}`;
|
const clipPathId = `clip-${page.pageIndex}-${card.data.id || card.x}-${card.y}`;
|
||||||
const shapeClipPath = getShapeSvgClipPath(clipPathId, cardWidth, cardHeight, store.state.shape);
|
const shapeClipPath = getShapeSvgClipPath(clipPathId, cardWidth, cardHeight, store.state.shape, store.state.cornerRadius);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g class="card-group">
|
<g class="card-group">
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,52 @@
|
||||||
import type { CardShape } from '../types';
|
import type { CardShape } from '../types';
|
||||||
|
import { getCardShapePoints, contourToSvgPath } from '../../../plotcutter/contour';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将轮廓点转换为 CSS polygon() 格式
|
||||||
|
* @param points 轮廓点数组(相对于左上角,单位:mm)
|
||||||
|
* @returns CSS polygon() 字符串,使用百分比坐标
|
||||||
|
*/
|
||||||
|
function pointsToCssPolygon(points: [number, number][], width: number, height: number): string {
|
||||||
|
if (points.length === 0) return 'none';
|
||||||
|
|
||||||
|
const coords = points.map(([x, y]) => {
|
||||||
|
const percentX = (x / width) * 100;
|
||||||
|
const percentY = (y / height) * 100;
|
||||||
|
return `${percentX.toFixed(4)}% ${percentY.toFixed(4)}%`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return `polygon(${coords.join(', ')})`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 CSS clip-path 值用于形状裁剪
|
* 获取 CSS clip-path 值用于形状裁剪
|
||||||
|
*
|
||||||
|
* @param shape 卡片形状
|
||||||
|
* @param width 卡片宽度(用于计算多边形坐标)
|
||||||
|
* @param height 卡片高度(用于计算多边形坐标)
|
||||||
|
* @param cornerRadius 圆角半径(可选,>0 时使用多边形近似)
|
||||||
|
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||||
*/
|
*/
|
||||||
export function getShapeClipPath(shape: CardShape): string {
|
export function getShapeClipPath(
|
||||||
switch (shape) {
|
shape: CardShape,
|
||||||
case 'circle':
|
width: number,
|
||||||
return 'circle(50% at 50% 50%)';
|
height: number,
|
||||||
case 'triangle':
|
cornerRadius: number = 0,
|
||||||
return 'polygon(50% 0%, 0% 100%, 100% 100%)';
|
segmentsPerCorner: number = 4
|
||||||
case 'hexagon':
|
): string {
|
||||||
return 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)';
|
// 无圆角的基本形状使用简化的 CSS clip-path
|
||||||
case 'rectangle':
|
if (cornerRadius <= 0) {
|
||||||
default:
|
switch (shape) {
|
||||||
return 'none';
|
case 'circle':
|
||||||
|
return 'circle(50% at 50% 50%)';
|
||||||
|
case 'rectangle':
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其他情况使用多边形近似(包括圆角形状、三角形、六边形)
|
||||||
|
const points = getCardShapePoints(shape, width, height, cornerRadius, segmentsPerCorner);
|
||||||
|
return pointsToCssPolygon(points, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,34 +55,41 @@ export function getShapeClipPath(shape: CardShape): string {
|
||||||
* @param width 卡片宽度
|
* @param width 卡片宽度
|
||||||
* @param height 卡片高度
|
* @param height 卡片高度
|
||||||
* @param shape 卡片形状
|
* @param shape 卡片形状
|
||||||
|
* @param cornerRadius 圆角半径(可选)
|
||||||
|
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||||
*/
|
*/
|
||||||
export function getShapeSvgClipPath(
|
export function getShapeSvgClipPath(
|
||||||
id: string,
|
id: string,
|
||||||
width: number,
|
width: number,
|
||||||
height: number,
|
height: number,
|
||||||
shape: CardShape
|
shape: CardShape,
|
||||||
|
cornerRadius: number = 0,
|
||||||
|
segmentsPerCorner: number = 4
|
||||||
): string {
|
): string {
|
||||||
const halfW = width / 2;
|
const points = getCardShapePoints(shape, width, height, cornerRadius, segmentsPerCorner);
|
||||||
const halfH = height / 2;
|
const pathData = contourToSvgPath(points, true);
|
||||||
|
|
||||||
switch (shape) {
|
return `
|
||||||
case 'circle':
|
|
||||||
return `
|
|
||||||
<clipPath id="${id}">
|
<clipPath id="${id}">
|
||||||
<circle cx="${halfW}" cy="${halfH}" r="${halfW}" />
|
<path d="${pathData}" />
|
||||||
</clipPath>`;
|
</clipPath>`;
|
||||||
case 'triangle':
|
}
|
||||||
return `
|
|
||||||
<clipPath id="${id}">
|
/**
|
||||||
<polygon points="${halfW},0 0,${height} ${width},${height}" />
|
* 获取卡片形状的 SVG path 数据
|
||||||
</clipPath>`;
|
* @param width 卡片宽度
|
||||||
case 'hexagon':
|
* @param height 卡片高度
|
||||||
return `
|
* @param shape 卡片形状
|
||||||
<clipPath id="${id}">
|
* @param cornerRadius 圆角半径(可选)
|
||||||
<polygon points="${halfW},0 ${width},${height * 0.25} ${width},${height * 0.75} ${halfW},${height} 0,${height * 0.75} 0,${height * 0.25}" />
|
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||||
</clipPath>`;
|
*/
|
||||||
case 'rectangle':
|
export function getCardShapePath(
|
||||||
default:
|
width: number,
|
||||||
return '';
|
height: number,
|
||||||
}
|
shape: CardShape,
|
||||||
|
cornerRadius: number = 0,
|
||||||
|
segmentsPerCorner: number = 4
|
||||||
|
): string {
|
||||||
|
const points = getCardShapePoints(shape, width, height, cornerRadius, segmentsPerCorner);
|
||||||
|
return contourToSvgPath(points, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue