diff --git a/frontend/src/components/ImageCanvas.css b/frontend/src/components/ImageCanvas.css index d3164e0..5ec2dd1 100644 --- a/frontend/src/components/ImageCanvas.css +++ b/frontend/src/components/ImageCanvas.css @@ -16,14 +16,27 @@ display: block; } -.clear-selection-btn { +.canvas-controls { position: absolute; - top: 10px; + bottom: 10px; + left: 10px; right: 10px; + display: flex; + justify-content: space-between; + align-items: center; + z-index: 10; + pointer-events: none; +} + +.canvas-controls > * { + pointer-events: auto; +} + +.clear-selection-btn { background-color: #ff4444; color: white; padding: 8px 16px; - z-index: 10; + border-radius: 4px; } .clear-selection-btn:hover { @@ -46,16 +59,12 @@ /* Zoom controls */ .zoom-controls { - position: absolute; - bottom: 10px; - right: 10px; display: flex; align-items: center; gap: 4px; background-color: rgba(0, 0, 0, 0.8); padding: 6px 10px; border-radius: 4px; - z-index: 10; } .zoom-controls button { diff --git a/frontend/src/components/ImageCanvas.jsx b/frontend/src/components/ImageCanvas.jsx index 86307ac..ff3a324 100644 --- a/frontend/src/components/ImageCanvas.jsx +++ b/frontend/src/components/ImageCanvas.jsx @@ -6,18 +6,23 @@ const ImageCanvas = forwardRef(({ imageUrl, onSelectionChange, selectionMode, - activeTool, + advancedToolMode, + onAdvancedToolClick, zoom = 100, onZoomChange, - onSmartSelect, + externalSelection, isProcessing }, ref) => { const canvasRef = useRef(null); const fabricCanvasRef = useRef(null); const [currentSelection, setCurrentSelection] = useState(null); + const [currentZoom, setCurrentZoom] = useState(1); const currentSelectionRef = useRef(null); const lassoPoints = useRef([]); const onZoomChangeRef = useRef(onZoomChange); + const imageRef = useRef(null); + const baseScaleRef = useRef(1); + const isDrawingRef = useRef(false); // Keep ref updated useEffect(() => { @@ -201,23 +206,23 @@ const ImageCanvas = forwardRef(({ canvas.off('object:moving'); canvas.off('object:scaling'); - // Set up handlers based on selection mode - if (selectionMode === 'rectangle') { + // Set up handlers based on selection mode or advanced tool mode + if (advancedToolMode === 'smart-select') { + setupSmartSelectMode(canvas); + } else if (advancedToolMode === 'color-select') { + setupColorSelectMode(canvas); + } else if (selectionMode === 'rectangle') { setupRectangleMode(canvas); } else if (selectionMode === 'ellipse') { setupEllipseMode(canvas); } else if (selectionMode === 'lasso') { setupLassoMode(canvas); - } else if (selectionMode === 'smart') { - setupSmartSelectMode(canvas); - } else if (selectionMode === 'color') { - setupColorSelectMode(canvas); - } else if (activeTool === 'move') { + } else if (selectionMode === 'move') { setupMoveMode(canvas); - } else if (activeTool === 'pan') { + } else if (selectionMode === 'pan') { setupPanMode(canvas); } - }, [selectionMode, activeTool, onSmartSelect]); + }, [selectionMode, advancedToolMode, onAdvancedToolClick, isProcessing]); const setupMoveMode = (canvas) => { // In move mode, allow selecting and moving selection objects @@ -284,7 +289,7 @@ const ImageCanvas = forwardRef(({ // Check if click is within image bounds if (x >= 0 && x < img.width && y >= 0 && y < img.height) { - onSmartSelect?.(x, y); + onAdvancedToolClick?.(x, y, null); } }); @@ -295,9 +300,38 @@ const ImageCanvas = forwardRef(({ canvas.on('mouse:down', (e) => { if (isProcessing) return; - // TODO: Get pixel color at click position const pointer = canvas.getPointer(e.e); - console.log('Color select at:', pointer); + const img = imageRef.current; + + if (!img) return; + + // Convert to image coordinates + const imgScale = img.scaleX; + const imgLeft = img.left; + const imgTop = img.top; + + const x = Math.round((pointer.x - imgLeft) / imgScale); + const y = Math.round((pointer.y - imgTop) / imgScale); + + // Check if click is within image bounds + if (x >= 0 && x < img.width && y >= 0 && y < img.height) { + // Get pixel color from canvas + const ctx = canvas.getContext('2d'); + if (ctx) { + // Calculate actual canvas position accounting for viewport transform + const vpt = canvas.viewportTransform; + const canvasX = pointer.x * vpt[0] + vpt[4]; + const canvasY = pointer.y * vpt[3] + vpt[5]; + + const pixelData = ctx.getImageData(canvasX, canvasY, 1, 1).data; + const color = { + r: pixelData[0], + g: pixelData[1], + b: pixelData[2] + }; + onAdvancedToolClick?.(x, y, color); + } + } }); canvas.setCursor('crosshair'); @@ -691,10 +725,23 @@ const ImageCanvas = forwardRef(({ return (
- {currentSelection && ( - +
+
+ + {Math.round(currentZoom * 100)}% + + +
+ {currentSelection && ( + + )} +
+ {(advancedToolMode === 'smart-select' || advancedToolMode === 'color-select') && ( +
+ {advancedToolMode === 'smart-select' ? 'Click on an object to select it' : 'Click on a color to select similar pixels'} +
)}
);