mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 13:45: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);
|
videoElement.addEventListener("load", onload);
|
||||||
return () => {
|
return () => {
|
||||||
|
console.log("unloading");
|
||||||
videoElement.removeEventListener("load", onload);
|
videoElement.removeEventListener("load", onload);
|
||||||
};
|
};
|
||||||
}, [videoElement]);
|
}, [videoElement]);
|
||||||
@ -112,34 +113,34 @@ export function PolygonCanvas({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseDown = (e: KonvaEventObject<MouseEvent>) => {
|
const handleMouseDown = (e: KonvaEventObject<MouseEvent>) => {
|
||||||
if (activePolygonIndex === null || !polygons) {
|
if (!activePolygonIndex || !polygons) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("mouse down polygons", polygons);
|
console.log("mouse down polygons", polygons);
|
||||||
console.log(activePolygonIndex);
|
console.log(activePolygonIndex);
|
||||||
|
|
||||||
if (!polygons[activePolygonIndex].points.length) {
|
// if (!polygons[activePolygonIndex].points.length) {
|
||||||
// Start a new polygon
|
// // Start a new polygon
|
||||||
const stage = e.target.getStage()!;
|
// const stage = e.target.getStage()!;
|
||||||
const mousePos = getMousePos(stage);
|
// const mousePos = getMousePos(stage);
|
||||||
setPolygons([
|
// setPolygons([
|
||||||
...polygons,
|
// ...polygons,
|
||||||
{
|
// {
|
||||||
name: "foo",
|
// name: "foo",
|
||||||
points: [mousePos],
|
// points: [mousePos],
|
||||||
isFinished: false,
|
// isFinished: false,
|
||||||
},
|
// },
|
||||||
]);
|
// ]);
|
||||||
setActivePolygonIndex(polygons.length);
|
// setActivePolygonIndex(polygons.length);
|
||||||
} else {
|
// } else {
|
||||||
const updatedPolygons = [...polygons];
|
const updatedPolygons = [...polygons];
|
||||||
const activePolygon = updatedPolygons[activePolygonIndex];
|
const activePolygon = updatedPolygons[activePolygonIndex];
|
||||||
const stage = e.target.getStage()!;
|
const stage = e.target.getStage()!;
|
||||||
const mousePos = getMousePos(stage);
|
const mousePos = getMousePos(stage);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isMouseOverPoint(activePolygon, mousePos) &&
|
activePolygon.points.length >= 3 &&
|
||||||
activePolygon.points.length >= 3
|
isMouseOverPoint(activePolygon, mousePos)
|
||||||
) {
|
) {
|
||||||
// Close the polygon
|
// Close the polygon
|
||||||
updatedPolygons[activePolygonIndex] = {
|
updatedPolygons[activePolygonIndex] = {
|
||||||
@ -158,7 +159,7 @@ export function PolygonCanvas({
|
|||||||
setPolygons(updatedPolygons);
|
setPolygons(updatedPolygons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseMove = (e: KonvaEventObject<MouseEvent>) => {
|
const handleMouseMove = (e: KonvaEventObject<MouseEvent>) => {
|
||||||
@ -177,16 +178,16 @@ export function PolygonCanvas({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseOutStartPoint = (e: KonvaEventObject<MouseEvent>) => {
|
const handleMouseOutStartPoint = (e: KonvaEventObject<MouseEvent>) => {
|
||||||
console.log("active index:", activePolygonIndex);
|
// console.log("active index:", activePolygonIndex);
|
||||||
e.currentTarget.scale({ x: 1, y: 1 });
|
e.currentTarget.scale({ x: 1, y: 1 });
|
||||||
if (activePolygonIndex !== null && polygons) {
|
if (activePolygonIndex !== null && polygons) {
|
||||||
const activePolygon = polygons[activePolygonIndex];
|
const activePolygon = polygons[activePolygonIndex];
|
||||||
console.log(activePolygon);
|
// console.log(activePolygon);
|
||||||
if (
|
if (
|
||||||
(!activePolygon.isFinished && activePolygon.points.length >= 3) ||
|
(!activePolygon.isFinished && activePolygon.points.length >= 3) ||
|
||||||
activePolygon.isFinished
|
activePolygon.isFinished
|
||||||
) {
|
) {
|
||||||
console.log(e.currentTarget);
|
// console.log(e.currentTarget);
|
||||||
e.currentTarget.scale({ x: 1, y: 1 });
|
e.currentTarget.scale({ x: 1, y: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,13 +238,14 @@ export function PolygonCanvas({
|
|||||||
setPolygons(updatedPolygons);
|
setPolygons(updatedPolygons);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// console.log("rendering canvas", Date.now());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stage
|
<Stage
|
||||||
ref={stageRef}
|
ref={stageRef}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
onMouseMove={handleMouseMove}
|
// onMouseMove={handleMouseMove}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
>
|
>
|
||||||
<Layer>
|
<Layer>
|
||||||
@ -255,8 +257,7 @@ export function PolygonCanvas({
|
|||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
/>
|
/>
|
||||||
{polygons &&
|
{polygons?.map((polygon, index) => (
|
||||||
polygons.map((polygon, index) => (
|
|
||||||
<PolygonDrawer
|
<PolygonDrawer
|
||||||
key={index}
|
key={index}
|
||||||
points={polygon.points}
|
points={polygon.points}
|
||||||
|
|||||||
@ -8,6 +8,14 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
@ -21,6 +29,7 @@ import { isDesktop } from "react-device-detect";
|
|||||||
import PolygonControls from "./PolygonControls";
|
import PolygonControls from "./PolygonControls";
|
||||||
import { Skeleton } from "../ui/skeleton";
|
import { Skeleton } from "../ui/skeleton";
|
||||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||||
|
import { LuPencil } from "react-icons/lu";
|
||||||
|
|
||||||
const parseCoordinates = (coordinatesString: string) => {
|
const parseCoordinates = (coordinatesString: string) => {
|
||||||
const coordinates = coordinatesString.split(",");
|
const coordinates = coordinatesString.split(",");
|
||||||
@ -97,26 +106,30 @@ export default function SettingsZones() {
|
|||||||
}
|
}
|
||||||
}, [cameraAspect]);
|
}, [cameraAspect]);
|
||||||
|
|
||||||
const [{ width: containerWidth, height: containerHeight }] =
|
// const [{ width: containerWidth, height: containerHeight }] =
|
||||||
useResizeObserver(containerRef);
|
// 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.
|
// Add scrollbar width (when visible) to the available observer width to eliminate screen juddering.
|
||||||
// https://github.com/blakeblackshear/frigate/issues/1657
|
// https://github.com/blakeblackshear/frigate/issues/1657
|
||||||
let scrollBarWidth = 0;
|
let scrollBarWidth = 0;
|
||||||
if (window.innerWidth && document.body.offsetWidth) {
|
// if (window.innerWidth && document.body.offsetWidth) {
|
||||||
scrollBarWidth = window.innerWidth - document.body.offsetWidth;
|
// scrollBarWidth = window.innerWidth - document.body.offsetWidth;
|
||||||
}
|
// }
|
||||||
const availableWidth = scrollBarWidth
|
// const availableWidth = scrollBarWidth
|
||||||
? containerWidth + scrollBarWidth
|
// ? containerWidth + scrollBarWidth
|
||||||
: containerWidth;
|
// : containerWidth;
|
||||||
|
|
||||||
|
const availableWidth = containerWidth;
|
||||||
|
|
||||||
const { width, height } = cameraConfig
|
const { width, height } = cameraConfig
|
||||||
? cameraConfig.detect
|
? cameraConfig.detect
|
||||||
: { width: 1, height: 1 };
|
: { width: 1, height: 1 };
|
||||||
const aspectRatio = width / height;
|
const aspectRatio = width / height;
|
||||||
|
|
||||||
const stretch = true;
|
const stretch = false;
|
||||||
const fitAspect = 1.8;
|
const fitAspect = 1;
|
||||||
const scaledHeight = useMemo(() => {
|
const scaledHeight = useMemo(() => {
|
||||||
const scaledHeight =
|
const scaledHeight =
|
||||||
aspectRatio < (fitAspect ?? 0)
|
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(() => {
|
// const image = useMemo(() => {
|
||||||
// if (cameraConfig && containerRef && containerRef.current) {
|
// if (cameraConfig && containerRef && containerRef.current) {
|
||||||
@ -193,7 +208,7 @@ export default function SettingsZones() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Heading as="h2">Motion Detection Tuner</Heading>
|
<Heading as="h2">Zones</Heading>
|
||||||
<div className="flex items-center space-x-2 mt-5">
|
<div className="flex items-center space-x-2 mt-5">
|
||||||
<Select value={selectedCamera} onValueChange={setSelectedCamera}>
|
<Select value={selectedCamera} onValueChange={setSelectedCamera}>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger className="w-[180px]">
|
||||||
@ -238,6 +253,48 @@ export default function SettingsZones() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[30%]">
|
<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
|
<PolygonControls
|
||||||
camera={cameraConfig.name}
|
camera={cameraConfig.name}
|
||||||
width={scaledWidth}
|
width={scaledWidth}
|
||||||
@ -256,8 +313,8 @@ export default function SettingsZones() {
|
|||||||
polygon.points,
|
polygon.points,
|
||||||
scaledWidth,
|
scaledWidth,
|
||||||
scaledHeight,
|
scaledHeight,
|
||||||
cameraConfig.detect.width,
|
1,
|
||||||
cameraConfig.detect.height,
|
1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
null,
|
null,
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export const interpolatePoints = (
|
|||||||
for (const [x, y] of points) {
|
for (const [x, y] of points) {
|
||||||
const newX = (x * newWidth) / width;
|
const newX = (x * newWidth) / width;
|
||||||
const newY = (y * newHeight) / height;
|
const newY = (y * newHeight) / height;
|
||||||
newPoints.push([Math.floor(newX), Math.floor(newY)]);
|
newPoints.push([newX, newY]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPoints;
|
return newPoints;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user