mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 05:35:25 +03:00
multi zones
This commit is contained in:
parent
8610b02ddb
commit
bbca5ffdfa
@ -72,6 +72,7 @@ export function PolygonCanvas({
|
||||
};
|
||||
videoElement.addEventListener("load", onload);
|
||||
return () => {
|
||||
console.log("unloading");
|
||||
videoElement.removeEventListener("load", onload);
|
||||
};
|
||||
}, [videoElement]);
|
||||
@ -112,53 +113,53 @@ export function PolygonCanvas({
|
||||
};
|
||||
|
||||
const handleMouseDown = (e: KonvaEventObject<MouseEvent>) => {
|
||||
if (activePolygonIndex === null || !polygons) {
|
||||
if (!activePolygonIndex || !polygons) {
|
||||
return;
|
||||
}
|
||||
console.log("mouse down polygons", polygons);
|
||||
console.log(activePolygonIndex);
|
||||
|
||||
if (!polygons[activePolygonIndex].points.length) {
|
||||
// Start a new polygon
|
||||
const stage = e.target.getStage()!;
|
||||
const mousePos = getMousePos(stage);
|
||||
setPolygons([
|
||||
...polygons,
|
||||
{
|
||||
name: "foo",
|
||||
points: [mousePos],
|
||||
isFinished: false,
|
||||
},
|
||||
]);
|
||||
setActivePolygonIndex(polygons.length);
|
||||
} else {
|
||||
const updatedPolygons = [...polygons];
|
||||
const activePolygon = updatedPolygons[activePolygonIndex];
|
||||
const stage = e.target.getStage()!;
|
||||
const mousePos = getMousePos(stage);
|
||||
// if (!polygons[activePolygonIndex].points.length) {
|
||||
// // Start a new polygon
|
||||
// const stage = e.target.getStage()!;
|
||||
// const mousePos = getMousePos(stage);
|
||||
// setPolygons([
|
||||
// ...polygons,
|
||||
// {
|
||||
// name: "foo",
|
||||
// points: [mousePos],
|
||||
// isFinished: false,
|
||||
// },
|
||||
// ]);
|
||||
// setActivePolygonIndex(polygons.length);
|
||||
// } else {
|
||||
const updatedPolygons = [...polygons];
|
||||
const activePolygon = updatedPolygons[activePolygonIndex];
|
||||
const stage = e.target.getStage()!;
|
||||
const mousePos = getMousePos(stage);
|
||||
|
||||
if (
|
||||
isMouseOverPoint(activePolygon, mousePos) &&
|
||||
activePolygon.points.length >= 3
|
||||
) {
|
||||
// Close the polygon
|
||||
if (
|
||||
activePolygon.points.length >= 3 &&
|
||||
isMouseOverPoint(activePolygon, mousePos)
|
||||
) {
|
||||
// Close the polygon
|
||||
updatedPolygons[activePolygonIndex] = {
|
||||
...activePolygon,
|
||||
isFinished: true,
|
||||
};
|
||||
setPolygons(updatedPolygons);
|
||||
// setActivePolygonIndex(null);
|
||||
} else {
|
||||
if (!activePolygon.isFinished) {
|
||||
// Add a new point to the active polygon
|
||||
updatedPolygons[activePolygonIndex] = {
|
||||
...activePolygon,
|
||||
isFinished: true,
|
||||
points: [...activePolygon.points, mousePos],
|
||||
};
|
||||
setPolygons(updatedPolygons);
|
||||
// setActivePolygonIndex(null);
|
||||
} else {
|
||||
if (!activePolygon.isFinished) {
|
||||
// Add a new point to the active polygon
|
||||
updatedPolygons[activePolygonIndex] = {
|
||||
...activePolygon,
|
||||
points: [...activePolygon.points, mousePos],
|
||||
};
|
||||
setPolygons(updatedPolygons);
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
const handleMouseMove = (e: KonvaEventObject<MouseEvent>) => {
|
||||
@ -177,16 +178,16 @@ export function PolygonCanvas({
|
||||
};
|
||||
|
||||
const handleMouseOutStartPoint = (e: KonvaEventObject<MouseEvent>) => {
|
||||
console.log("active index:", activePolygonIndex);
|
||||
// console.log("active index:", activePolygonIndex);
|
||||
e.currentTarget.scale({ x: 1, y: 1 });
|
||||
if (activePolygonIndex !== null && polygons) {
|
||||
const activePolygon = polygons[activePolygonIndex];
|
||||
console.log(activePolygon);
|
||||
// console.log(activePolygon);
|
||||
if (
|
||||
(!activePolygon.isFinished && activePolygon.points.length >= 3) ||
|
||||
activePolygon.isFinished
|
||||
) {
|
||||
console.log(e.currentTarget);
|
||||
// console.log(e.currentTarget);
|
||||
e.currentTarget.scale({ x: 1, y: 1 });
|
||||
}
|
||||
}
|
||||
@ -237,13 +238,14 @@ export function PolygonCanvas({
|
||||
setPolygons(updatedPolygons);
|
||||
}
|
||||
};
|
||||
// console.log("rendering canvas", Date.now());
|
||||
|
||||
return (
|
||||
<Stage
|
||||
ref={stageRef}
|
||||
width={width}
|
||||
height={height}
|
||||
onMouseMove={handleMouseMove}
|
||||
// onMouseMove={handleMouseMove}
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<Layer>
|
||||
@ -255,20 +257,19 @@ export function PolygonCanvas({
|
||||
width={width}
|
||||
height={height}
|
||||
/>
|
||||
{polygons &&
|
||||
polygons.map((polygon, index) => (
|
||||
<PolygonDrawer
|
||||
key={index}
|
||||
points={polygon.points}
|
||||
flattenedPoints={flattenPoints(polygon.points)}
|
||||
isActive={index === activePolygonIndex}
|
||||
isFinished={polygon.isFinished}
|
||||
handlePointDragMove={handlePointDragMove}
|
||||
handleGroupDragEnd={handleGroupDragEnd}
|
||||
handleMouseOverStartPoint={handleMouseOverStartPoint}
|
||||
handleMouseOutStartPoint={handleMouseOutStartPoint}
|
||||
/>
|
||||
))}
|
||||
{polygons?.map((polygon, index) => (
|
||||
<PolygonDrawer
|
||||
key={index}
|
||||
points={polygon.points}
|
||||
flattenedPoints={flattenPoints(polygon.points)}
|
||||
isActive={index === activePolygonIndex}
|
||||
isFinished={polygon.isFinished}
|
||||
handlePointDragMove={handlePointDragMove}
|
||||
handleGroupDragEnd={handleGroupDragEnd}
|
||||
handleMouseOverStartPoint={handleMouseOverStartPoint}
|
||||
handleMouseOutStartPoint={handleMouseOutStartPoint}
|
||||
/>
|
||||
))}
|
||||
</Layer>
|
||||
</Stage>
|
||||
);
|
||||
|
||||
@ -8,6 +8,14 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import useSWR from "swr";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
@ -21,6 +29,7 @@ import { isDesktop } from "react-device-detect";
|
||||
import PolygonControls from "./PolygonControls";
|
||||
import { Skeleton } from "../ui/skeleton";
|
||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||
import { LuPencil } from "react-icons/lu";
|
||||
|
||||
const parseCoordinates = (coordinatesString: string) => {
|
||||
const coordinates = coordinatesString.split(",");
|
||||
@ -97,26 +106,30 @@ export default function SettingsZones() {
|
||||
}
|
||||
}, [cameraAspect]);
|
||||
|
||||
const [{ width: containerWidth, height: containerHeight }] =
|
||||
useResizeObserver(containerRef);
|
||||
// const [{ width: containerWidth, height: containerHeight }] =
|
||||
// useResizeObserver(containerRef);
|
||||
const containerWidth = containerRef.current?.clientWidth;
|
||||
const containerHeight = containerRef.current?.clientHeight;
|
||||
|
||||
// Add scrollbar width (when visible) to the available observer width to eliminate screen juddering.
|
||||
// https://github.com/blakeblackshear/frigate/issues/1657
|
||||
let scrollBarWidth = 0;
|
||||
if (window.innerWidth && document.body.offsetWidth) {
|
||||
scrollBarWidth = window.innerWidth - document.body.offsetWidth;
|
||||
}
|
||||
const availableWidth = scrollBarWidth
|
||||
? containerWidth + scrollBarWidth
|
||||
: containerWidth;
|
||||
// if (window.innerWidth && document.body.offsetWidth) {
|
||||
// scrollBarWidth = window.innerWidth - document.body.offsetWidth;
|
||||
// }
|
||||
// const availableWidth = scrollBarWidth
|
||||
// ? containerWidth + scrollBarWidth
|
||||
// : containerWidth;
|
||||
|
||||
const availableWidth = containerWidth;
|
||||
|
||||
const { width, height } = cameraConfig
|
||||
? cameraConfig.detect
|
||||
: { width: 1, height: 1 };
|
||||
const aspectRatio = width / height;
|
||||
|
||||
const stretch = true;
|
||||
const fitAspect = 1.8;
|
||||
const stretch = false;
|
||||
const fitAspect = 1;
|
||||
const scaledHeight = useMemo(() => {
|
||||
const scaledHeight =
|
||||
aspectRatio < (fitAspect ?? 0)
|
||||
@ -158,7 +171,9 @@ export default function SettingsZones() {
|
||||
})),
|
||||
);
|
||||
}
|
||||
}, [cameraConfig, containerRef, scaledWidth, scaledHeight]);
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [cameraConfig, containerRef]);
|
||||
|
||||
// const image = useMemo(() => {
|
||||
// if (cameraConfig && containerRef && containerRef.current) {
|
||||
@ -193,7 +208,7 @@ export default function SettingsZones() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Heading as="h2">Motion Detection Tuner</Heading>
|
||||
<Heading as="h2">Zones</Heading>
|
||||
<div className="flex items-center space-x-2 mt-5">
|
||||
<Select value={selectedCamera} onValueChange={setSelectedCamera}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
@ -238,6 +253,48 @@ export default function SettingsZones() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[30%]">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Name</TableHead>
|
||||
<TableHead className="max-w-[200px]">Coordinates</TableHead>
|
||||
<TableHead>Edit</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{zonePolygons.map((polygon, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell className="font-medium">
|
||||
{polygon.name}
|
||||
</TableCell>
|
||||
<TableCell className="max-w-[200px] text-wrap">
|
||||
<code>
|
||||
{JSON.stringify(
|
||||
interpolatePoints(
|
||||
polygon.points,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
cameraConfig.detect.width,
|
||||
cameraConfig.detect.height,
|
||||
),
|
||||
null,
|
||||
0,
|
||||
)}
|
||||
</code>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{" "}
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => setActivePolygonIndex(index)}
|
||||
>
|
||||
<LuPencil className="size-4 text-white" />
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<PolygonControls
|
||||
camera={cameraConfig.name}
|
||||
width={scaledWidth}
|
||||
@ -256,8 +313,8 @@ export default function SettingsZones() {
|
||||
polygon.points,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
cameraConfig.detect.width,
|
||||
cameraConfig.detect.height,
|
||||
1,
|
||||
1,
|
||||
),
|
||||
),
|
||||
null,
|
||||
|
||||
@ -58,7 +58,7 @@ export const interpolatePoints = (
|
||||
for (const [x, y] of points) {
|
||||
const newX = (x * newWidth) / width;
|
||||
const newY = (y * newHeight) / height;
|
||||
newPoints.push([Math.floor(newX), Math.floor(newY)]);
|
||||
newPoints.push([newX, newY]);
|
||||
}
|
||||
|
||||
return newPoints;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user