Add a coordinate system and mouse tracking to the canvas
Adds X and Y axis labels to the canvas, displays mouse coordinates on hover, and updates the project documentation to reflect these new features. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 0385ea33-cde8-4bbd-8fce-8d192d30eb41 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/870d08ce-da3b-4822-9874-c2fe2b7628b1/0385ea33-cde8-4bbd-8fce-8d192d30eb41/zNDeQGA
This commit is contained in:
@@ -24,6 +24,7 @@ export function Canvas({
|
|||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const [zoom, setZoom] = useState(1);
|
const [zoom, setZoom] = useState(1);
|
||||||
const [pixelSize, setPixelSize] = useState(8);
|
const [pixelSize, setPixelSize] = useState(8);
|
||||||
|
const [mouseCoords, setMouseCoords] = useState<{x: number, y: number} | null>(null);
|
||||||
|
|
||||||
// Create pixel map for O(1) lookup
|
// Create pixel map for O(1) lookup
|
||||||
const pixelMap = new Map<string, string>();
|
const pixelMap = new Map<string, string>();
|
||||||
@@ -36,6 +37,14 @@ export function Canvas({
|
|||||||
onPixelClick(x, y);
|
onPixelClick(x, y);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePixelMouseEnter = (x: number, y: number) => {
|
||||||
|
setMouseCoords({ x, y });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePixelMouseLeave = () => {
|
||||||
|
setMouseCoords(null);
|
||||||
|
};
|
||||||
|
|
||||||
const handleZoomIn = () => {
|
const handleZoomIn = () => {
|
||||||
setZoom(prev => Math.min(prev * 1.2, 3));
|
setZoom(prev => Math.min(prev * 1.2, 3));
|
||||||
};
|
};
|
||||||
@@ -67,11 +76,49 @@ export function Canvas({
|
|||||||
className="w-full h-full overflow-auto p-8"
|
className="w-full h-full overflow-auto p-8"
|
||||||
data-testid="canvas-container"
|
data-testid="canvas-container"
|
||||||
>
|
>
|
||||||
<div
|
{/* Coordinate System Container */}
|
||||||
className="grid mx-auto border border-gray-400 relative"
|
<div className="relative inline-block">
|
||||||
style={canvasStyle}
|
{/* Top X-axis coordinates */}
|
||||||
data-testid="pixel-canvas"
|
<div className="flex ml-8 mb-1">
|
||||||
>
|
{Array.from({ length: Math.ceil(canvasWidth / 10) }, (_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="text-xs text-gray-400 text-center"
|
||||||
|
style={{
|
||||||
|
width: `${10 * pixelSize}px`,
|
||||||
|
fontSize: `${Math.max(8, pixelSize * 0.8)}px`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i * 10}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Canvas with left Y-axis coordinates */}
|
||||||
|
<div className="flex">
|
||||||
|
{/* Left Y-axis coordinates */}
|
||||||
|
<div className="flex flex-col mr-1">
|
||||||
|
{Array.from({ length: Math.ceil(canvasHeight / 10) }, (_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="text-xs text-gray-400 flex items-center justify-end"
|
||||||
|
style={{
|
||||||
|
height: `${10 * pixelSize}px`,
|
||||||
|
width: '24px',
|
||||||
|
fontSize: `${Math.max(8, pixelSize * 0.8)}px`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i * 10}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Canvas */}
|
||||||
|
<div
|
||||||
|
className="grid border border-gray-400 relative"
|
||||||
|
style={canvasStyle}
|
||||||
|
data-testid="pixel-canvas"
|
||||||
|
>
|
||||||
{Array.from({ length: canvasHeight }, (_, y) =>
|
{Array.from({ length: canvasHeight }, (_, y) =>
|
||||||
Array.from({ length: canvasWidth }, (_, x) => {
|
Array.from({ length: canvasWidth }, (_, x) => {
|
||||||
const pixelColor = pixelMap.get(`${x},${y}`) || "#FFFFFF";
|
const pixelColor = pixelMap.get(`${x},${y}`) || "#FFFFFF";
|
||||||
@@ -88,6 +135,8 @@ export function Canvas({
|
|||||||
height: `${pixelSize}px`
|
height: `${pixelSize}px`
|
||||||
}}
|
}}
|
||||||
onClick={() => handlePixelClick(x, y)}
|
onClick={() => handlePixelClick(x, y)}
|
||||||
|
onMouseEnter={() => handlePixelMouseEnter(x, y)}
|
||||||
|
onMouseLeave={handlePixelMouseLeave}
|
||||||
data-testid={`pixel-${x}-${y}`}
|
data-testid={`pixel-${x}-${y}`}
|
||||||
data-x={x}
|
data-x={x}
|
||||||
data-y={y}
|
data-y={y}
|
||||||
@@ -95,9 +144,26 @@ export function Canvas({
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Coordinate Info Display */}
|
||||||
|
<div className="absolute top-4 left-4 bg-panel-bg px-3 py-2 rounded-lg border border-gray-600">
|
||||||
|
<div className="text-sm text-gray-300">
|
||||||
|
Canvas: {canvasWidth} × {canvasHeight}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-400">
|
||||||
|
Zoom: {Math.round(zoom * 100)}%
|
||||||
|
</div>
|
||||||
|
{mouseCoords && (
|
||||||
|
<div className="text-xs text-green-400 mt-1">
|
||||||
|
Mouse: ({mouseCoords.x}, {mouseCoords.y})
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Zoom Controls */}
|
{/* Zoom Controls */}
|
||||||
<div className="absolute bottom-4 right-4 flex flex-col space-y-2">
|
<div className="absolute bottom-4 right-4 flex flex-col space-y-2">
|
||||||
<button
|
<button
|
||||||
|
|||||||
1
exports/canvas-2025-08-18T12-27-25-417Z.svg
Normal file
1
exports/canvas-2025-08-18T12-27-25-417Z.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#FFFFFF"/><rect x="64" y="7" width="1" height="1" fill="#be0039"/><rect x="65" y="7" width="1" height="1" fill="#00ccc0"/></svg>
|
||||||
|
After Width: | Height: | Size: 232 B |
@@ -45,10 +45,12 @@ Language: German (Deutsch) - User communicates in German and prefers responses i
|
|||||||
|
|
||||||
**User Experience Features**
|
**User Experience Features**
|
||||||
- Interactive canvas with zoom and pan capabilities
|
- Interactive canvas with zoom and pan capabilities
|
||||||
- Color palette with 16 predefined colors
|
- Official r/place 2022 color palette with 32 authentic colors arranged in 8x4 grid
|
||||||
|
- Coordinate system with X/Y axis labels showing every 10th position
|
||||||
|
- Real-time mouse coordinate tracking and display
|
||||||
- Cooldown system to prevent pixel spam
|
- Cooldown system to prevent pixel spam
|
||||||
- Recent placements tracking and display
|
- Recent placements tracking and display
|
||||||
- Grid overlay toggle for precise pixel placement
|
- Canvas size and zoom level information display
|
||||||
- Toast notifications for user feedback
|
- Toast notifications for user feedback
|
||||||
|
|
||||||
## External Dependencies
|
## External Dependencies
|
||||||
|
|||||||
Reference in New Issue
Block a user