feat: magic wand tool

This commit is contained in:
trafficlunar 2025-01-19 13:22:54 +00:00
parent fb90ae5f26
commit 0cb18092ee
3 changed files with 61 additions and 9 deletions

View file

@ -301,6 +301,43 @@ function Canvas() {
const onClick = useCallback(() => { const onClick = useCallback(() => {
switch (tool) { switch (tool) {
case "magic-wand": {
const visited = new Set<string>();
const result: CoordinateArray = [];
const startBlock = blocks.find((block) => block.x === mouseCoords.x && block.y === mouseCoords.y);
// Return if the block is not found
if (!startBlock) return result;
function depthFirstSearch(block: Block) {
const key = `${block.x},${block.y}`;
if (visited.has(key)) return;
visited.add(key);
result.push([block.x, block.y]);
// Directions for adjacent blocks (up, down, left, right)
const directions = [
{ dx: 0, dy: 1 },
{ dx: 0, dy: -1 },
{ dx: 1, dy: 0 },
{ dx: -1, dy: 0 },
];
for (const { dx, dy } of directions) {
const newX = block.x + dx;
const newY = block.y + dy;
const adjacentBlock = blocks.find((b) => b.x === newX && b.y === newY && b.name === block.name);
if (adjacentBlock) {
depthFirstSearch({ ...block, x: newX, y: newY });
}
}
}
depthFirstSearch({ name: startBlock.name, x: mouseCoords.x, y: mouseCoords.y });
setSelectionCoords(result);
break;
}
case "eyedropper": { case "eyedropper": {
const mouseBlock = blocks.find((block) => block.x === mouseCoords.x && block.y === mouseCoords.y); const mouseBlock = blocks.find((block) => block.x === mouseCoords.x && block.y === mouseCoords.y);
if (mouseBlock) setSelectedBlock(mouseBlock.name); if (mouseBlock) setSelectedBlock(mouseBlock.name);
@ -347,15 +384,18 @@ function Canvas() {
setTool("lasso"); setTool("lasso");
break; break;
case "5": case "5":
setTool("pencil"); setTool("magic-wand");
break; break;
case "6": case "6":
setTool("eraser"); setTool("pencil");
break; break;
case "7": case "7":
setTool("eyedropper"); setTool("eraser");
break; break;
case "8": case "8":
setTool("eyedropper");
break;
case "9":
setTool("zoom"); setTool("zoom");
break; break;
} }

View file

@ -1,5 +1,5 @@
import { useContext } from "react"; import { useContext } from "react";
import { EraserIcon, HandIcon, LassoIcon, MousePointer2Icon, PencilIcon, PipetteIcon, SquareDashedIcon, ZoomInIcon } from "lucide-react"; import { EraserIcon, HandIcon, LassoIcon, MousePointer2Icon, PencilIcon, PipetteIcon, SquareDashedIcon, WandIcon, ZoomInIcon } from "lucide-react";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
@ -69,6 +69,18 @@ function Toolbar() {
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
{/* Magic Wand */}
<Tooltip delayDuration={0}>
<TooltipTrigger>
<ToggleGroupItem value="magic-wand" className="!p-0 !h-8 !min-w-8">
<WandIcon />
</ToggleGroupItem>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={10}>
<p>Magic Wand (5)</p>
</TooltipContent>
</Tooltip>
{/* Pencil */} {/* Pencil */}
<Tooltip delayDuration={0}> <Tooltip delayDuration={0}>
<TooltipTrigger> <TooltipTrigger>
@ -77,7 +89,7 @@ function Toolbar() {
</ToggleGroupItem> </ToggleGroupItem>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="right" sideOffset={10}> <TooltipContent side="right" sideOffset={10}>
<p>Pencil (5)</p> <p>Pencil (6)</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
@ -89,7 +101,7 @@ function Toolbar() {
</ToggleGroupItem> </ToggleGroupItem>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="right" sideOffset={10}> <TooltipContent side="right" sideOffset={10}>
<p>Eraser (6)</p> <p>Eraser (7)</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
@ -101,7 +113,7 @@ function Toolbar() {
</ToggleGroupItem> </ToggleGroupItem>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="right" sideOffset={10}> <TooltipContent side="right" sideOffset={10}>
<p>Eyedropper (7)</p> <p>Eyedropper (8)</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
@ -113,7 +125,7 @@ function Toolbar() {
</ToggleGroupItem> </ToggleGroupItem>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="right" sideOffset={10}> <TooltipContent side="right" sideOffset={10}>
<p>Zoom (8)</p> <p>Zoom (9)</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>

2
src/types.d.ts vendored
View file

@ -23,7 +23,7 @@ interface Block extends Position {
type CoordinateArray = [number, number][]; type CoordinateArray = [number, number][];
type Tool = "hand" | "move" | "rectangle-select" | "lasso" | "pencil" | "eraser" | "eyedropper" | "zoom"; type Tool = "hand" | "move" | "rectangle-select" | "lasso" | "magic-wand" | "pencil" | "eraser" | "eyedropper" | "zoom";
interface Settings { interface Settings {
grid: boolean; grid: boolean;