mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-10 21:25:24 +03:00
new zone dialog
This commit is contained in:
parent
0863d43e04
commit
3659c4a678
Binary file not shown.
|
Before Width: | Height: | Size: 144 KiB |
@ -1,5 +1,14 @@
|
||||
import { Button } from "../ui/button";
|
||||
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 = {
|
||||
camera: string;
|
||||
@ -17,6 +26,11 @@ export function PolygonControls({
|
||||
activePolygonIndex,
|
||||
setActivePolygonIndex,
|
||||
}: PolygonCanvasProps) {
|
||||
const { data: config } = useSWR("config");
|
||||
const [zoneName, setZoneName] = useState<string | null>();
|
||||
const [invalidName, setInvalidName] = useState<boolean>();
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
|
||||
const undo = () => {
|
||||
if (activePolygonIndex !== null && polygons) {
|
||||
const updatedPolygons = [...polygons];
|
||||
@ -44,13 +58,13 @@ export function PolygonControls({
|
||||
}
|
||||
};
|
||||
|
||||
const handleNewPolygon = () => {
|
||||
const handleNewPolygon = (zoneName: string) => {
|
||||
setPolygons([
|
||||
...(polygons || []),
|
||||
{
|
||||
points: [],
|
||||
isFinished: false,
|
||||
name: "new",
|
||||
name: zoneName,
|
||||
},
|
||||
]);
|
||||
setActivePolygonIndex(polygons.length);
|
||||
@ -65,9 +79,57 @@ export function PolygonControls({
|
||||
<Button variant="secondary" onClick={reset}>
|
||||
Reset
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={handleNewPolygon}>
|
||||
New Polygon
|
||||
<Button variant="secondary" onClick={() => setDialogOpen(true)}>
|
||||
New Zone
|
||||
</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>
|
||||
);
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user