1. 設計工作室架構
設計工作室是 核心創意工具 POD 平台 — 讓設計人員直接在網頁瀏覽器中建立、編輯和匯出設計。
┌──────────────────────────────────────────────────────────┐
│ Design Studio UI │
│ ┌──────┐ ┌──────────────────────────────┐ ┌──────────┐ │
│ │Panels│ │ Canvas Area │ │Properties│ │
│ │ │ │ ┌────────────────────────┐ │ │ Panel │ │
│ │Layers│ │ │ │ │ │ │ │
│ │Assets│ │ │ [Canvas Renderer] │ │ │ Fill │ │
│ │Text │ │ │ WebGL / Canvas 2D │ │ │ Stroke │ │
│ │AI Gen│ │ │ │ │ │ Font │ │
│ │ │ │ └────────────────────────┘ │ │ Effects │ │
│ └──────┘ └──────────────────────────────┘ └──────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Toolbar: Select | Text | Shape | Image | AI | Undo │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
2. Canvas渲染器架構
// Canvas Engine — Fabric.js based architecture
interface CanvasEngine {
// Core rendering
renderer: WebGLRenderer | Canvas2DRenderer;
scene: SceneGraph;
viewport: Viewport;
// Object management
objects: DesignObject[];
selectedObjects: DesignObject[];
// History
undoStack: CanvasState[];
redoStack: CanvasState[];
}
type DesignObject =
| TextObject
| ImageObject
| ShapeObject
| GroupObject
| ClipPathObject;
interface TextObject {
type: 'text';
id: string;
content: string;
fontFamily: string;
fontSize: number;
fill: string | Gradient | Pattern;
position: { x: number; y: number };
rotation: number;
opacity: number;
effects: TextEffect[];
// Print-specific
outlineForPrint: boolean; // Convert text → paths for RIP
}
interface ImageObject {
type: 'image';
id: string;
src: string; // Original hi-res URL
thumbnail: string; // Preview thumbnail
position: { x: number; y: number };
size: { width: number; height: number };
cropRect?: CropRect;
filters: ImageFilter[];
// Print-specific
dpi: number; // >= 300 for print
colorSpace: 'rgb' | 'cmyk';
}
渲染管線
User Action → Command → Scene Graph Update → Render Queue
│
┌─────▼──────┐
│ Dirty Rect │
│ Detection │
└─────┬──────┘
│
┌─────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│Background│ │ Objects │ │ Overlay │
│ Layer │ │ Layer │ │ Layer │
│(template)│ │(designs) │ │(guides, │
│ │ │ │ │ handles) │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└─────────────┼──────────────┘
▼
Composited Frame
→ Display
3. 圖層系統
interface LayerManager {
layers: Layer[];
addLayer(object: DesignObject): Layer;
removeLayer(layerId: string): void;
reorderLayer(layerId: string, newIndex: number): void;
groupLayers(layerIds: string[]): GroupLayer;
// Visibility & locking
toggleVisibility(layerId: string): void;
toggleLock(layerId: string): void;
// Blending
setBlendMode(layerId: string, mode: BlendMode): void;
setOpacity(layerId: string, opacity: number): void;
}
type BlendMode =
| 'normal' | 'multiply' | 'screen' | 'overlay'
| 'darken' | 'lighten' | 'color-dodge' | 'color-burn';
interface Layer {
id: string;
name: string;
object: DesignObject;
visible: boolean;
locked: boolean;
blendMode: BlendMode;
opacity: number;
zIndex: number;
}
4. 模板引擎
interface DesignTemplate {
id: string;
name: string;
category: 'tshirt' | 'hoodie' | 'mug' | 'poster' | 'phone_case';
// Canvas dimensions
canvas: {
width: number; // pixels at 300 DPI
height: number;
dpi: number;
};
// Print area definition
printArea: {
x: number;
y: number;
width: number;
height: number;
safeZone: number; // margin from edge
};
// Pre-placed elements (editable placeholders)
placeholders: Array<{
id: string;
type: 'text' | 'image' | 'shape';
label: string; // "Your text here"
position: Position;
style: Partial;
editable: boolean;
required: boolean;
}>;
// Background/mockup preview
previewMockup: string; // Product image with design area overlay
}
// Template cho T-shirt Front
const tshirtFrontTemplate: DesignTemplate = {
id: 'tmpl-tshirt-front-standard',
name: 'T-Shirt Front — Standard',
category: 'tshirt',
canvas: { width: 4500, height: 5400, dpi: 300 }, // 15" x 18" at 300 DPI
printArea: { x: 150, y: 150, width: 4200, height: 5100, safeZone: 75 },
placeholders: [
{
id: 'main-text',
type: 'text',
label: 'Your Design Here',
position: { x: 2250, y: 2700 },
style: { fontSize: 200, fontFamily: 'Inter', fill: '#ffffff' },
editable: true,
required: false,
}
],
previewMockup: '/mockups/tshirt-front-preview.png',
};
5. 資源庫和字體管理
interface AssetLibrary {
// Categories
categories: AssetCategory[];
// Search & filter
search(query: string, filters: AssetFilter): Promise<Asset[]>;
// User uploads
uploadAsset(file: File, metadata: AssetMetadata): Promise<Asset>;
}
interface Asset {
id: string;
type: 'clipart' | 'icon' | 'photo' | 'pattern' | 'font' | 'ai_generated';
name: string;
thumbnail: string;
fullUrl: string;
tags: string[];
license: 'free' | 'premium' | 'user_uploaded';
// Technical
format: 'svg' | 'png' | 'webp';
dimensions?: { width: number; height: number };
fileSize: number;
transparent: boolean;
}
// Font loading strategy
interface FontManager {
// System fonts pre-loaded
systemFonts: FontFace[];
// On-demand loading
loadFont(fontFamily: string): Promise<FontFace>;
// Font subsetting for export (only glyphs used)
subsetFont(fontFamily: string, text: string): Promise<ArrayBuffer>;
// Convert text to paths (for RIP compatibility)
textToPath(textObject: TextObject): Promise<SVGPathElement>;
}
6. 出口管道
Canvas State
│
├── Preview Export (fast, low-res)
│ └── WebP, 72 DPI, max 1200px → CDN
│
├── Mockup Export (medium)
│ └── PNG, 150 DPI, product composite → CDN
│
└── Print Export (high-res, production)
│
├── Text → Paths (outline fonts)
├── Images → full resolution
├── Color space conversion (RGB → CMYK if needed)
├── Add bleed & trim marks
├── Flatten layers
└── Output:
├── PNG (300 DPI, transparent background) — for DTG/DTF
├── PDF/X-4 (CMYK, ICC profile) — for offset/sublimation
└── SVG (vector) — for vinyl cut/screen print
interface ExportService {
exportForPreview(canvasState: CanvasState): Promise<string> ; // WebP URL
exportForMockup(canvasState: CanvasState, template: MockupTemplate): Promise<string>;
exportForPrint(canvasState: CanvasState, printSpec: PrintSpec): Promise<PrintFile>;
}
interface PrintSpec {
format: 'png' | 'pdf' | 'svg';
dpi: number; // 300 for most, 600 for fine art
colorSpace: 'rgb' | 'cmyk';
iccProfile?: string; // 'USWebCoatedSWOP' | 'sRGB'
bleed: number; // mm
includeTriMarks: boolean;
flattenLayers: boolean;
textToOutlines: boolean;
}
interface PrintFile {
url: string;
format: string;
width: number;
height: number;
dpi: number;
colorSpace: string;
fileSizeBytes: number;
checksum: string; // SHA-256 for integrity
}
7. 撤銷/重做和狀態管理
// Command pattern for undo/redo
interface CanvasCommand {
execute(): void;
undo(): void;
description: string;
}
class MoveObjectCommand implements CanvasCommand {
constructor(
private object: DesignObject,
private from: Position,
private to: Position,
) {}
execute() { this.object.position = this.to; }
undo() { this.object.position = this.from; }
description = 'Move object';
}
class HistoryManager {
private undoStack: CanvasCommand[] = [];
private redoStack: CanvasCommand[] = [];
private maxHistory = 50;
execute(command: CanvasCommand) {
command.execute();
this.undoStack.push(command);
this.redoStack = []; // Clear redo on new action
if (this.undoStack.length > this.maxHistory) {
this.undoStack.shift();
}
}
undo() {
const command = this.undoStack.pop();
if (command) {
command.undo();
this.redoStack.push(command);
}
}
redo() {
const command = this.redoStack.pop();
if (command) {
command.execute();
this.undoStack.push(command);
}
}
}
八、總結
畫布引擎 — WebGL/Canvas 2D 渲染、髒矩形優化、60fps 目標
圖層系統 — Z 順序、混合模式、分組、可見性/鎖定
模板引擎 — 具有列印區域、佔位符、安全區的產品特定模板
資源庫 — 剪貼畫、圖示、圖案、字體、AI 生成的資源
出口管道 — 預覽 (72 DPI WebP) → 模型 (150 DPI PNG) → 列印(300 DPI 列印就緒)
撤銷/重做 — 命令模式,50步驟歷史記錄