feat: shape for cards
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { calculateDimensions } from './dimensions';
|
||||
import { loadCSV, CSV } from '../../utils/csv-loader';
|
||||
import { initLayerConfigs, formatLayers, initLayerConfigsForSide } from './layer-parser';
|
||||
import type { CardData, LayerConfig, Dimensions, CardSide } from '../types';
|
||||
import type { CardData, LayerConfig, Dimensions, CardSide, CardShape } from '../types';
|
||||
|
||||
/**
|
||||
* 默认配置常量
|
||||
@@ -24,6 +24,7 @@ export interface DeckState {
|
||||
gridH: number;
|
||||
bleed: number;
|
||||
padding: number;
|
||||
shape: CardShape;
|
||||
fixed: boolean;
|
||||
src: string;
|
||||
rawSrc: string; // 原始 CSV 路径(用于生成代码时保持相对路径)
|
||||
@@ -75,6 +76,7 @@ export interface DeckActions {
|
||||
setGridH: (grid: number) => void;
|
||||
setBleed: (bleed: number) => void;
|
||||
setPadding: (padding: number) => void;
|
||||
setShape: (shape: CardShape) => void;
|
||||
|
||||
// 数据设置
|
||||
setCards: (cards: CSV<CardData>) => void;
|
||||
@@ -144,6 +146,7 @@ export function createDeckStore(
|
||||
gridH: DECK_DEFAULTS.GRID_H,
|
||||
bleed: DECK_DEFAULTS.BLEED,
|
||||
padding: DECK_DEFAULTS.PADDING,
|
||||
shape: 'rectangle',
|
||||
fixed: false,
|
||||
src: initialSrc,
|
||||
rawSrc: initialSrc,
|
||||
@@ -206,6 +209,9 @@ export function createDeckStore(
|
||||
setState({ padding });
|
||||
updateDimensions();
|
||||
};
|
||||
const setShape = (shape: CardShape) => {
|
||||
setState({ shape });
|
||||
};
|
||||
|
||||
const setCards = (cards: CSV<CardData>) => setState({ cards, activeTab: 0 });
|
||||
const setActiveTab = (index: number) => setState({ activeTab: index });
|
||||
@@ -313,6 +319,9 @@ export function createDeckStore(
|
||||
if (state.padding !== DECK_DEFAULTS.PADDING) {
|
||||
parts.push(`padding="${state.padding}" `);
|
||||
}
|
||||
if (state.shape !== 'rectangle') {
|
||||
parts.push(`shape="${state.shape}" `);
|
||||
}
|
||||
|
||||
parts.push(`layers="${frontLayersStr}" `);
|
||||
if (backLayersString) {
|
||||
@@ -368,6 +377,7 @@ export function createDeckStore(
|
||||
setGridH,
|
||||
setBleed,
|
||||
setPadding,
|
||||
setShape,
|
||||
setCards,
|
||||
setActiveTab,
|
||||
updateCardData,
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { CardShape } from '../types';
|
||||
|
||||
/**
|
||||
* 获取 CSS clip-path 值用于形状裁剪
|
||||
*/
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 SVG clipPath 定义
|
||||
* @param id clipPath 的唯一 ID
|
||||
* @param width 卡片宽度
|
||||
* @param height 卡片高度
|
||||
* @param shape 卡片形状
|
||||
*/
|
||||
export function getShapeSvgClipPath(
|
||||
id: string,
|
||||
width: number,
|
||||
height: number,
|
||||
shape: CardShape
|
||||
): string {
|
||||
const halfW = width / 2;
|
||||
const halfH = height / 2;
|
||||
|
||||
switch (shape) {
|
||||
case 'circle':
|
||||
return `
|
||||
<clipPath id="${id}">
|
||||
<circle cx="${halfW}" cy="${halfH}" r="${halfW}" />
|
||||
</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 '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user