feat: add pencil tool

This commit is contained in:
trafficlunar 2024-12-05 22:02:15 +00:00
parent f50f109d27
commit 6f5fdfb799
2 changed files with 57 additions and 9 deletions

View file

@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Layer, Stage } from "react-konva"; import { Layer, Stage } from "react-konva";
import { Hand } from "lucide-react"; import { Hand, Pencil } from "lucide-react";
import { import {
Menubar, Menubar,
@ -34,9 +34,25 @@ function App() {
const [mousePosition, setMousePosition] = useState<Position>({ x: 0, y: 0 }); const [mousePosition, setMousePosition] = useState<Position>({ x: 0, y: 0 });
const [tool, setTool] = useState<Tool>("hand"); const [tool, setTool] = useState<Tool>("hand");
const [selectedBlock, setSelectedBlock] = useState("stone");
const [blocks, setBlocks] = useState<Block[]>([]); const [blocks, setBlocks] = useState<Block[]>([]);
const [cssCursor, setCssCursor] = useState("grab"); const [cssCursor, setCssCursor] = useState("grab");
const [mouseDown, setMouseDown] = useState(false);
const onToolChange = (value) => {
setTool(value);
switch (value) {
case "hand":
setCssCursor("grab");
break;
default:
setCssCursor("auto");
break;
}
};
const onMouseMove = (e) => { const onMouseMove = (e) => {
const stage = e.target.getStage(); const stage = e.target.getStage();
@ -47,15 +63,15 @@ function App() {
x: (pointer.x - stage.x()) / oldScale, x: (pointer.x - stage.x()) / oldScale,
y: (pointer.y - stage.y()) / oldScale, y: (pointer.y - stage.y()) / oldScale,
}); });
};
const onMouseDown = (e) => { if (mouseDown) {
if (tool == "hand") { onClick(e);
setCssCursor("grabbing");
} }
}; };
const onMouseUp = (e) => { const onMouseUp = (e) => {
setMouseDown(false);
if (tool == "hand") { if (tool == "hand") {
setCssCursor("grab"); setCssCursor("grab");
} }
@ -75,6 +91,28 @@ function App() {
}); });
}; };
const onClick = (e) => {
switch (tool) {
case "hand":
setCssCursor("grabbing");
break;
case "pencil": {
const blockX = Math.floor(mousePosition.x / 16);
const blockY = Math.floor(mousePosition.y / 16);
const updatedBlocks = blocks.filter((b) => !(b.x === blockX && b.y === blockY));
setBlocks([
...updatedBlocks,
{
name: selectedBlock,
x: blockX,
y: blockY,
},
]);
}
}
};
useEffect(() => { useEffect(() => {
if (stageContainerRef.current && stageRef.current) { if (stageContainerRef.current && stageRef.current) {
setStageSize({ setStageSize({
@ -118,26 +156,36 @@ function App() {
</MenubarMenu> </MenubarMenu>
</Menubar> </Menubar>
<ToggleGroup type="single" size={"sm"} value={tool} className="flex flex-col justify-start py-0.5 border-r border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950"> <ToggleGroup
type="single"
size={"sm"}
value={tool}
onValueChange={onToolChange}
className="flex flex-col gap-0.5 justify-start py-0.5 border-r border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950"
>
<ToggleGroupItem value="hand"> <ToggleGroupItem value="hand">
<Hand /> <Hand />
</ToggleGroupItem> </ToggleGroupItem>
<ToggleGroupItem value="pencil">
<Pencil />
</ToggleGroupItem>
</ToggleGroup> </ToggleGroup>
<div ref={stageContainerRef} className="relative w-full h-full"> <div ref={stageContainerRef} className="relative w-full h-full">
<Stage <Stage
width={stageSize.width} width={stageSize.width}
height={stageSize.height} height={stageSize.height}
draggable draggable={tool == "hand"}
ref={stageRef} ref={stageRef}
x={stageCoords.x} x={stageCoords.x}
y={stageCoords.y} y={stageCoords.y}
scaleX={stageScale} scaleX={stageScale}
scaleY={stageScale} scaleY={stageScale}
onMouseMove={onMouseMove} onMouseMove={onMouseMove}
onMouseDown={onMouseDown} onMouseDown={() => setMouseDown(true)}
onMouseUp={onMouseUp} onMouseUp={onMouseUp}
onWheel={onWheel} onWheel={onWheel}
onClick={onClick}
style={{ cursor: cssCursor }} style={{ cursor: cssCursor }}
> >
<Layer imageSmoothingEnabled={false}> <Layer imageSmoothingEnabled={false}>

2
src/types.d.ts vendored
View file

@ -7,4 +7,4 @@ interface Block extends Position {
name: string; name: string;
} }
type Tool = "hand"; type Tool = "hand" | "pencil";