/** * Lasso Tool - Free polygon selection for mask */ import { Point } from './brush-tool' export interface LassoToolOptions { color: string } export class LassoTool { private ctx: CanvasRenderingContext2D private isDrawing: boolean = false private points: Point[] = [] private options: LassoToolOptions private previewCanvas: HTMLCanvasElement | null = null constructor(ctx: CanvasRenderingContext2D, options: LassoToolOptions) { this.ctx = ctx this.options = options } setColor(color: string) { this.options.color = color } setPreviewCanvas(canvas: HTMLCanvasElement) { this.previewCanvas = canvas } // Add point on click addPoint(point: Point) { if (!this.isDrawing) { this.isDrawing = true this.points = [] } this.points.push(point) this.drawPreview() } // Draw preview polygon private drawPreview() { if (!this.previewCanvas || this.points.length === 0) return const previewCtx = this.previewCanvas.getContext('2d') if (!previewCtx) return previewCtx.clearRect(0, 0, this.previewCanvas.width, this.previewCanvas.height) // Draw polygon outline previewCtx.strokeStyle = this.options.color previewCtx.lineWidth = 2 previewCtx.setLineDash([5, 5]) previewCtx.beginPath() previewCtx.moveTo(this.points[0].x, this.points[0].y) for (let i = 1; i < this.points.length; i++) { previewCtx.lineTo(this.points[i].x, this.points[i].y) } previewCtx.stroke() // Draw points this.points.forEach((p, i) => { previewCtx.fillStyle = i === 0 ? '#00ff00' : this.options.color previewCtx.beginPath() previewCtx.arc(p.x, p.y, 4, 0, Math.PI * 2) previewCtx.fill() }) } // Close and fill polygon on double-click closePath() { if (!this.isDrawing || this.points.length < 3) { this.cancel() return } // Fill polygon on mask this.ctx.fillStyle = this.options.color this.ctx.beginPath() this.ctx.moveTo(this.points[0].x, this.points[0].y) for (let i = 1; i < this.points.length; i++) { this.ctx.lineTo(this.points[i].x, this.points[i].y) } this.ctx.closePath() this.ctx.fill() this.cancel() } cancel() { this.isDrawing = false this.points = [] if (this.previewCanvas) { const ctx = this.previewCanvas.getContext('2d') ctx?.clearRect(0, 0, this.previewCanvas.width, this.previewCanvas.height) } } isActive(): boolean { return this.isDrawing } getPointCount(): number { return this.points.length } }