feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full selection system with multiple selection tools, operations, and visual feedback. **New Files:** - types/selection.ts: Selection types, masks, and state interfaces - lib/selection-utils.ts: Selection mask generation and manipulation algorithms - lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations - store/selection-store.ts: Selection state management with Zustand - core/commands/selection-command.ts: Undo/redo commands for selections - tools/rectangular-selection-tool.ts: Rectangular marquee selection - tools/elliptical-selection-tool.ts: Elliptical marquee selection - tools/lasso-selection-tool.ts: Free-form polygon selection - tools/magic-wand-tool.ts: Color-based flood-fill selection - components/selection/selection-panel.tsx: Complete selection UI panel - components/selection/index.ts: Selection components barrel export **Updated Files:** - components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation - components/editor/editor-layout.tsx: Integrated SelectionPanel into layout - store/index.ts: Added selection-store export - store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts - tools/index.ts: Added selection tool exports - types/index.ts: Added selection types export - types/canvas.ts: Renamed Selection interface to CanvasSelection **Selection Tools:** **Marquee Tools:** - ✨ Rectangular Selection: Click-drag rectangular regions - ✨ Elliptical Selection: Click-drag elliptical regions **Free-form Tools:** - ✨ Lasso Selection: Draw free-form polygon selections - ✨ Magic Wand: Color-based flood-fill selection with tolerance **Selection Modes:** - 🔷 New: Replace existing selection - ➕ Add: Add to existing selection - ➖ Subtract: Remove from existing selection - ⚡ Intersect: Keep only overlapping areas **Selection Operations:** - 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask - 🗑️ Delete: Remove selected pixels - 🎨 Fill Selection: Fill with current color - 🖌️ Stroke Selection: Outline selection with current color - 🔄 Invert Selection: Invert selected/unselected pixels - ❌ Clear Selection: Deselect all **Technical Features:** - Marching ants animation (animated dashed outline at 50ms interval) - Selection masks using Uint8Array (0-255 values for anti-aliasing) - Feathering support (0-250px gaussian blur on selection edges) - Tolerance control for magic wand (0-255 color difference threshold) - Scanline polygon fill algorithm for lasso tool - Flood-fill with Set-based visited tracking for magic wand - Selection bounds calculation for optimized operations - Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I) - Undo/redo integration via selection commands - Non-destructive operations with proper history tracking **Algorithm Implementations:** - Rectangular mask: Simple bounds-based pixel marking - Elliptical mask: Distance formula from ellipse center - Lasso mask: Scanline polygon fill with edge intersection - Magic wand: BFS flood-fill with color tolerance matching - Mask combination: Per-pixel operations (max, subtract, AND) - Feathering: Separable box blur (horizontal + vertical passes) - Mask inversion: Per-pixel NOT operation with bounds recalculation **UI/UX Features:** - 264px wide selection panel with all tools and operations - Tool selection with visual feedback (highlighted active tool) - Selection mode toggles (new/add/subtract/intersect) - Feather and tolerance sliders with live value display - Disabled state when no selection exists - Keyboard shortcut hints next to operations - Visual marching ants animation (animated dashes) Build verified: ✓ Compiled successfully in 1302ms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -25,9 +25,9 @@ export interface CanvasState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Selection interface for selected regions
|
||||
* Canvas selection interface for selected regions (deprecated - use Selection from selection.ts)
|
||||
*/
|
||||
export interface Selection {
|
||||
export interface CanvasSelection {
|
||||
/** Is there an active selection */
|
||||
active: boolean;
|
||||
/** Selection bounds */
|
||||
|
||||
@@ -3,3 +3,4 @@ export * from './layer';
|
||||
export * from './tool';
|
||||
export * from './history';
|
||||
export * from './filter';
|
||||
export * from './selection';
|
||||
|
||||
47
types/selection.ts
Normal file
47
types/selection.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
export type SelectionType = 'rectangular' | 'elliptical' | 'lasso' | 'magic-wand';
|
||||
|
||||
export type SelectionMode = 'new' | 'add' | 'subtract' | 'intersect';
|
||||
|
||||
export interface SelectionBounds {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selection mask is a 2D boolean array representing selected pixels
|
||||
* true = selected, false = not selected
|
||||
*/
|
||||
export interface SelectionMask {
|
||||
width: number;
|
||||
height: number;
|
||||
data: Uint8Array; // 1 byte per pixel (0 = not selected, 255 = selected)
|
||||
bounds: SelectionBounds;
|
||||
}
|
||||
|
||||
export interface Selection {
|
||||
id: string;
|
||||
layerId: string;
|
||||
mask: SelectionMask;
|
||||
inverted: boolean;
|
||||
feather: number; // Feather radius in pixels
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface SelectionState {
|
||||
activeSelection: Selection | null;
|
||||
selectionType: SelectionType;
|
||||
selectionMode: SelectionMode;
|
||||
feather: number;
|
||||
tolerance: number; // For magic wand (0-255)
|
||||
isMarching: boolean; // Marching ants animation
|
||||
}
|
||||
|
||||
/**
|
||||
* Point for lasso selection
|
||||
*/
|
||||
export interface LassoPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
Reference in New Issue
Block a user