diff --git a/src/components/DrawingCanvas.js b/src/components/DrawingCanvas.js index 2c4959a..625b866 100644 --- a/src/components/DrawingCanvas.js +++ b/src/components/DrawingCanvas.js @@ -1,59 +1,81 @@ import React, { useRef, useState, useEffect } from 'react'; import { ChromePicker } from 'react-color'; -const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setHistory }) => { +// Drawing utilities +const drawLine = (ctx, x1, y1, x2, y2, color, thickness) => { + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.strokeStyle = color || '#000000'; + ctx.lineWidth = thickness || 2; + ctx.lineCap = 'round'; + ctx.stroke(); +}; + +const drawShape = (ctx, shape) => { + ctx.beginPath(); + ctx.strokeStyle = shape.color || '#000000'; + ctx.lineWidth = shape.thickness || 2; + ctx.lineCap = 'round'; + + if (shape.type === 'rectangle') { + ctx.rect(shape.x || 0, shape.y || 0, shape.width || 0, shape.height || 0); + } else if (shape.type === 'circle') { + ctx.arc(shape.x || 0, shape.y || 0, shape.radius || 0, 0, Math.PI * 2); + } + + ctx.stroke(); +}; + +const DrawingCanvas = () => { const canvasRef = useRef(null); const [isDrawing, setIsDrawing] = useState(false); const [currentTool, setCurrentTool] = useState('pencil'); + const [color, setColor] = useState('#000000'); + const [thickness, setThickness] = useState(2); + const [history, setHistory] = useState([]); const [shapes, setShapes] = useState([]); const [lastPosition, setLastPosition] = useState(null); + const [undoHistory, setUndoHistory] = useState([]); useEffect(() => { const canvas = canvasRef.current; + if (!canvas) return; + const ctx = canvas.getContext('2d'); + if (!ctx) return; // Set initial canvas size canvas.width = window.innerWidth - 300; canvas.height = window.innerHeight - 100; - // Draw history + // Clear canvas first + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // Draw all shapes + shapes.forEach((shape) => { + drawShape(ctx, shape); + }); + + // Draw all pencil strokes from history history.forEach((action) => { if (action.type === 'draw') { drawLine(ctx, action.x1, action.y1, action.x2, action.y2, action.color, action.thickness); } }); - // Draw shapes shapes.forEach((shape) => { drawShape(ctx, shape); }); + + // Draw history (for pencil drawing) + history.forEach((action) => { + if (action.type === 'draw') { + drawLine(ctx, action.x1, action.y1, action.x2, action.y2, action.color, action.thickness); + } + }); }, [history, shapes]); - const drawLine = (ctx, x1, y1, x2, y2, color, thickness) => { - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.strokeStyle = color; - ctx.lineWidth = thickness; - ctx.lineCap = 'round'; - ctx.stroke(); - }; - - const drawShape = (ctx, shape) => { - ctx.beginPath(); - ctx.strokeStyle = shape.color; - ctx.lineWidth = shape.thickness; - ctx.lineCap = 'round'; - - if (shape.type === 'rectangle') { - ctx.rect(shape.x, shape.y, shape.width, shape.height); - } else if (shape.type === 'circle') { - ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2); - } - - ctx.stroke(); - }; - const handleMouseDown = (e) => { setIsDrawing(true); const canvas = canvasRef.current; @@ -108,7 +130,7 @@ const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setH ctx.stroke(); // Update history - setHistory([...history, { + setHistory(prevHistory => [...prevHistory, { type: 'draw', x1: lastPos.x, y1: lastPos.y, @@ -136,45 +158,56 @@ const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setH } return shape; }); + + // Add shape to history when it's created + if (updatedShapes.length > 0) { + const lastShape = updatedShapes[updatedShapes.length - 1]; + setHistory(prevHistory => [...prevHistory, { + type: 'shape', + shape: lastShape + }]); + } + setShapes(updatedShapes); } }; - // Separate function to handle shape drawing - useEffect(() => { - const canvas = canvasRef.current; - const ctx = canvas.getContext('2d'); - - // Clear canvas and redraw all shapes - ctx.clearRect(0, 0, canvas.width, canvas.height); - - // Draw all shapes - shapes.forEach((shape) => { - drawShape(ctx, shape); - }); - - // Draw history (for pencil drawing) - history.forEach((action) => { - if (action.type === 'draw') { - drawLine(ctx, action.x1, action.y1, action.x2, action.y2, action.color, action.thickness); - } - }); - }, [shapes, history]); - const handleMouseUp = () => { setIsDrawing(false); - // Clear last position when mouse is released setLastPosition(null); + setUndoHistory([]); }; const handleUndo = () => { if (history.length > 0) { - setHistory(history.slice(0, -1)); + // Clear the last action from history + setHistory(prevHistory => prevHistory.slice(0, -1)); + + // Add it to undo history + setUndoHistory(prev => [...prev, history[history.length - 1]]); + + // Clear the last shape if it exists + if (shapes.length > 0) { + setShapes(prevShapes => prevShapes.slice(0, -1)); + } } }; const handleRedo = () => { - // Implement redo functionality + if (undoHistory.length > 0) { + const lastUndo = undoHistory[undoHistory.length - 1]; + + // Add the action back to history + setHistory(prevHistory => [...prevHistory, lastUndo]); + + // Remove it from undo history + setUndoHistory(prev => prev.slice(0, -1)); + + // Add the shape back if it exists + if (lastUndo.type === 'shape') { + setShapes(prevShapes => [...prevShapes, lastUndo.shape]); + } + } }; return ( @@ -189,10 +222,10 @@ const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setH - -
@@ -211,9 +244,6 @@ const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setH onMouseDown={handleMouseDown} onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} - max="20" - value={thickness} - onChange={(e) => setThickness(e.target.value)} />