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(() =>
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ export function PrintPreview(props: PrintPreviewProps) {
|
|||
const cardWidth = store.state.dimensions?.cardWidth || 56;
|
||||
const cardHeight = store.state.dimensions?.cardHeight || 88;
|
||||
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 (
|
||||
<g class="card-group">
|
||||
|
|
|
|||
|
|
@ -1,20 +1,52 @@
|
|||
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 值用于形状裁剪
|
||||
*
|
||||
* @param shape 卡片形状
|
||||
* @param width 卡片宽度(用于计算多边形坐标)
|
||||
* @param height 卡片高度(用于计算多边形坐标)
|
||||
* @param cornerRadius 圆角半径(可选,>0 时使用多边形近似)
|
||||
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||
*/
|
||||
export function getShapeClipPath(shape: CardShape): string {
|
||||
switch (shape) {
|
||||
case 'circle':
|
||||
return 'circle(50% at 50% 50%)';
|
||||
case 'triangle':
|
||||
return 'polygon(50% 0%, 0% 100%, 100% 100%)';
|
||||
case 'hexagon':
|
||||
return 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)';
|
||||
case 'rectangle':
|
||||
default:
|
||||
return 'none';
|
||||
export function getShapeClipPath(
|
||||
shape: CardShape,
|
||||
width: number,
|
||||
height: number,
|
||||
cornerRadius: number = 0,
|
||||
segmentsPerCorner: number = 4
|
||||
): string {
|
||||
// 无圆角的基本形状使用简化的 CSS clip-path
|
||||
if (cornerRadius <= 0) {
|
||||
switch (shape) {
|
||||
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 height 卡片高度
|
||||
* @param shape 卡片形状
|
||||
* @param cornerRadius 圆角半径(可选)
|
||||
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||
*/
|
||||
export function getShapeSvgClipPath(
|
||||
id: string,
|
||||
width: number,
|
||||
height: number,
|
||||
shape: CardShape
|
||||
shape: CardShape,
|
||||
cornerRadius: number = 0,
|
||||
segmentsPerCorner: number = 4
|
||||
): string {
|
||||
const halfW = width / 2;
|
||||
const halfH = height / 2;
|
||||
const points = getCardShapePoints(shape, width, height, cornerRadius, segmentsPerCorner);
|
||||
const pathData = contourToSvgPath(points, true);
|
||||
|
||||
switch (shape) {
|
||||
case 'circle':
|
||||
return `
|
||||
return `
|
||||
<clipPath id="${id}">
|
||||
<circle cx="${halfW}" cy="${halfH}" r="${halfW}" />
|
||||
<path d="${pathData}" />
|
||||
</clipPath>`;
|
||||
case 'triangle':
|
||||
return `
|
||||
<clipPath id="${id}">
|
||||
<polygon points="${halfW},0 0,${height} ${width},${height}" />
|
||||
</clipPath>`;
|
||||
case 'hexagon':
|
||||
return `
|
||||
<clipPath id="${id}">
|
||||
<polygon points="${halfW},0 ${width},${height * 0.25} ${width},${height * 0.75} ${halfW},${height} 0,${height * 0.75} 0,${height * 0.25}" />
|
||||
</clipPath>`;
|
||||
case 'rectangle':
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取卡片形状的 SVG path 数据
|
||||
* @param width 卡片宽度
|
||||
* @param height 卡片高度
|
||||
* @param shape 卡片形状
|
||||
* @param cornerRadius 圆角半径(可选)
|
||||
* @param segmentsPerCorner 每个圆角的分段数(可选)
|
||||
*/
|
||||
export function getCardShapePath(
|
||||
width: number,
|
||||
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