Files
ttrpg-tools/src/components/md-deck/hooks/shape-styles.ts
T

96 lines
2.8 KiB
TypeScript

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,
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);
}
/**
* 获取 SVG clipPath 定义
* @param id clipPath 的唯一 ID
* @param width 卡片宽度
* @param height 卡片高度
* @param shape 卡片形状
* @param cornerRadius 圆角半径(可选)
* @param segmentsPerCorner 每个圆角的分段数(可选)
*/
export function getShapeSvgClipPath(
id: string,
width: number,
height: number,
shape: CardShape,
cornerRadius: number = 0,
segmentsPerCorner: number = 4
): string {
const points = getCardShapePoints(shape, width, height, cornerRadius, segmentsPerCorner);
const pathData = contourToSvgPath(points, true);
return `
<clipPath id="${id}">
<path d="${pathData}" />
</clipPath>`;
}
/**
* 获取卡片形状的 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);
}