new zone dialog

This commit is contained in:
Josh Hawkins 2024-04-09 08:46:26 -05:00
parent 0863d43e04
commit 3659c4a678
3 changed files with 66 additions and 184 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

View File

@ -1,5 +1,14 @@
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { Polygon } from "@/types/canvas"; import { Polygon } from "@/types/canvas";
import {
Dialog,
DialogContent,
DialogFooter,
DialogTitle,
} from "@/components/ui/dialog";
import { useState } from "react";
import { Input } from "../ui/input";
import useSWR from "swr";
type PolygonCanvasProps = { type PolygonCanvasProps = {
camera: string; camera: string;
@ -17,6 +26,11 @@ export function PolygonControls({
activePolygonIndex, activePolygonIndex,
setActivePolygonIndex, setActivePolygonIndex,
}: PolygonCanvasProps) { }: PolygonCanvasProps) {
const { data: config } = useSWR("config");
const [zoneName, setZoneName] = useState<string | null>();
const [invalidName, setInvalidName] = useState<boolean>();
const [dialogOpen, setDialogOpen] = useState(false);
const undo = () => { const undo = () => {
if (activePolygonIndex !== null && polygons) { if (activePolygonIndex !== null && polygons) {
const updatedPolygons = [...polygons]; const updatedPolygons = [...polygons];
@ -44,13 +58,13 @@ export function PolygonControls({
} }
}; };
const handleNewPolygon = () => { const handleNewPolygon = (zoneName: string) => {
setPolygons([ setPolygons([
...(polygons || []), ...(polygons || []),
{ {
points: [], points: [],
isFinished: false, isFinished: false,
name: "new", name: zoneName,
}, },
]); ]);
setActivePolygonIndex(polygons.length); setActivePolygonIndex(polygons.length);
@ -65,9 +79,57 @@ export function PolygonControls({
<Button variant="secondary" onClick={reset}> <Button variant="secondary" onClick={reset}>
Reset Reset
</Button> </Button>
<Button variant="secondary" onClick={handleNewPolygon}> <Button variant="secondary" onClick={() => setDialogOpen(true)}>
New Polygon New Zone
</Button> </Button>
<Dialog
open={dialogOpen}
onOpenChange={(open) => {
setDialogOpen(open);
if (!open) {
setZoneName("");
}
}}
>
<DialogContent>
<DialogTitle>New Zone</DialogTitle>
<>
<Input
className="mt-3"
type="search"
value={zoneName ?? ""}
onChange={(e) => {
setInvalidName(
Object.keys(config.cameras).includes(e.target.value),
);
setZoneName(e.target.value);
}}
/>
{invalidName && (
<div className="text-danger text-sm">
Zone names must not be the name of a camera.
</div>
)}
<DialogFooter>
<Button
size="sm"
variant="select"
disabled={invalidName || (zoneName?.length ?? 0) == 0}
onClick={() => {
if (zoneName) {
setDialogOpen(false);
handleNewPolygon(zoneName);
}
setZoneName(null);
}}
>
Continue
</Button>
</DialogFooter>
</>
</DialogContent>
</Dialog>
</div> </div>
</div> </div>
); );

View File

@ -1,180 +0,0 @@
import { useEffect, useRef, useState } from "react";
import Konva from "konva";
import { Stage, Layer, Line, Circle, Transformer } from "react-konva";
import useDoubleClick from "@/hooks/use-double-click";
export default function PolygonDrawer() {
const [points, setPoints] = useState<number[]>([]);
const [anchors, setAnchors] = useState<Konva.Circle[]>([]);
const [lastPointIndex, setLastPointIndex] = useState(0);
const [isDrawing, setIsDrawing] = useState(false);
const [selectedAnchorIndex, setSelectedAnchorIndex] = useState<number | null>(
null,
);
const containerRef = useRef<HTMLDivElement>(null);
const stageRef = useRef<Konva.Stage>(null);
const layerRef = useRef<Konva.Layer>(null);
const handleMouseDown = () => {
if (!stageRef.current) {
return;
}
const stage = stageRef.current.getStage();
const mousePos = stage?.getPointerPosition();
if (!mousePos) return;
const updatedPoints = [...points];
updatedPoints.push(mousePos.x, mousePos.y);
setPoints(updatedPoints);
const newAnchor = new Konva.Circle({
x: mousePos.x,
y: mousePos.y,
radius: 5,
fill: "blue",
draggable: true,
name: "anchor",
});
setAnchors((prevAnchors) => [...prevAnchors, newAnchor]);
layerRef.current?.add(newAnchor);
setIsDrawing(true);
};
console.log(isDrawing);
const handleMouseMove = () => {
const stage = stageRef.current?.getStage();
const mousePos = stage?.getPointerPosition();
if (!mousePos || !isDrawing) return;
const updatedPoints = [...points];
updatedPoints[updatedPoints.length - 2] = mousePos.x;
updatedPoints[updatedPoints.length - 1] = mousePos.y;
setPoints(updatedPoints);
layerRef.current?.batchDraw();
};
const handleDoubleClick = () => {
alert("double clicked 1");
const layer = layerRef.current;
console.log(layer);
if (!layer) return;
console.log("double clicked");
document.body.style.background = "red";
const tempLine = layerRef.current.findOne(".temp");
if (tempLine) tempLine.destroy();
const polyObj = new Konva.Line({
points,
name: "poly",
fill: "green",
stroke: "red",
strokeWidth: 1,
draggable: true,
closed: true,
hitStrokeWidth: 10,
});
layerRef.current.add(polyObj);
layerRef.current.batchDraw();
setIsDrawing(false);
setLastPointIndex(0);
setPoints([]);
setAnchors([]);
};
const handleStageClick = (e: Konva.KonvaEventObject<MouseEvent>) => {
const clickedTarget = e.target;
if (clickedTarget instanceof Konva.Circle) {
const index = anchors.findIndex((anchor) => anchor === clickedTarget);
setSelectedAnchorIndex(index);
} else {
setSelectedAnchorIndex(null);
}
};
const handleAnchorDragMove = (index: number) => {
const stage = stageRef.current?.getStage();
const mousePos = stage?.getPointerPosition();
if (!mousePos) return;
const updatedAnchors = [...anchors];
updatedAnchors[index] = new Konva.Circle({
...updatedAnchors[index].attrs,
x: mousePos.x,
y: mousePos.y,
});
setAnchors(updatedAnchors);
const updatedPoints = [...points];
updatedPoints[index * 2] = mousePos.x;
updatedPoints[index * 2 + 1] = mousePos.y;
setPoints(updatedPoints);
layerRef.current?.batchDraw();
};
useEffect(() => {
const stage = stageRef.current;
if (stage) {
console.log(stage);
stage.on("mousedown", handleMouseDown);
stage.on("mousemove", handleMouseMove);
stage.on("dblclick", handleDoubleClick);
}
return () => {
if (stage) {
stage.off("mousedown", handleMouseDown);
stage.off("mousemove", handleMouseMove);
stage.off("dblclick", handleDoubleClick);
}
};
}, []);
console.log(points);
return (
<div id="konva" ref={containerRef}>
<Stage
width={600}
height={480}
// onDblClick={(e) => {
// e.cancelBubble = true;
// console.log("dbl");
// handleDoubleClick();
// }}
// onMouseDown={handleMouseDown}
// onMouseMove={handleMouseMove}
// onClick={handleStageClick}
ref={stageRef}
>
<Layer ref={layerRef}>
{isDrawing && (
<Line
points={points}
name="temp"
fill="green"
stroke="red"
strokeWidth={1}
draggable={false}
/>
)}
{anchors.map((anchor, index) => (
<Circle
key={index}
x={anchor.x()}
y={anchor.y()}
radius={5}
fill={selectedAnchorIndex === index ? "red" : "blue"}
draggable
onDragMove={(e) => handleAnchorDragMove(index, e)}
/>
))}
</Layer>
</Stage>
<div id="debug">debug</div>
</div>
);
}