main
parent
a6ba03cb47
commit
84ee8cfaec
|
@ -1,59 +1,81 @@
|
|||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import { ChromePicker } from 'react-color';
|
||||
|
||||
const DrawingCanvas = ({ color, setColor, thickness, setThickness, history, setHistory }) => {
|
||||
const canvasRef = useRef(null);
|
||||
const [isDrawing, setIsDrawing] = useState(false);
|
||||
const [currentTool, setCurrentTool] = useState('pencil');
|
||||
const [shapes, setShapes] = useState([]);
|
||||
const [lastPosition, setLastPosition] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Set initial canvas size
|
||||
canvas.width = window.innerWidth - 300;
|
||||
canvas.height = window.innerHeight - 100;
|
||||
|
||||
// Draw 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);
|
||||
});
|
||||
}, [history, shapes]);
|
||||
|
||||
// Drawing utilities
|
||||
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.strokeStyle = color || '#000000';
|
||||
ctx.lineWidth = thickness || 2;
|
||||
ctx.lineCap = 'round';
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
const drawShape = (ctx, shape) => {
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = shape.color;
|
||||
ctx.lineWidth = shape.thickness;
|
||||
ctx.strokeStyle = shape.color || '#000000';
|
||||
ctx.lineWidth = shape.thickness || 2;
|
||||
ctx.lineCap = 'round';
|
||||
|
||||
if (shape.type === 'rectangle') {
|
||||
ctx.rect(shape.x, shape.y, shape.width, shape.height);
|
||||
ctx.rect(shape.x || 0, shape.y || 0, shape.width || 0, shape.height || 0);
|
||||
} else if (shape.type === 'circle') {
|
||||
ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);
|
||||
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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
|
||||
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 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
|
|||
<button onClick={() => setCurrentTool('circle')} className={`tool-button ${currentTool === 'circle' ? 'active' : ''}`}>
|
||||
⭕
|
||||
</button>
|
||||
<button onClick={handleUndo} className="tool-button">
|
||||
<button onClick={handleUndo} className="tool-button" disabled={history.length === 0}>
|
||||
↺
|
||||
</button>
|
||||
<button onClick={handleRedo} className="tool-button">
|
||||
<button onClick={handleRedo} className="tool-button" disabled={undoHistory.length === 0}>
|
||||
↻
|
||||
</button>
|
||||
<div className="color-picker">
|
||||
|
@ -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)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue