mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 02:29:19 +03:00
fix masks and zones layout issues at high browser zoom levels (#22181)
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
This commit is contained in:
parent
4232cc483d
commit
1f1d546326
@ -258,7 +258,7 @@ export function PolygonCanvas({
|
|||||||
const updatedPolygons = [...polygons];
|
const updatedPolygons = [...polygons];
|
||||||
const activePolygon = updatedPolygons[activePolygonIndex];
|
const activePolygon = updatedPolygons[activePolygonIndex];
|
||||||
|
|
||||||
if (containerRef.current && !activePolygon.isFinished) {
|
if (containerRef.current && activePolygon && !activePolygon.isFinished) {
|
||||||
containerRef.current.style.cursor = "crosshair";
|
containerRef.current.style.cursor = "crosshair";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -329,7 +329,7 @@ export default function PolygonItem({
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="transition-background my-1.5 flex flex-row items-center justify-between rounded-lg p-1 duration-100"
|
className="transition-background relative my-1.5 flex flex-row items-center justify-between rounded-lg p-1 duration-100"
|
||||||
data-index={index}
|
data-index={index}
|
||||||
onMouseEnter={() => setHoveredPolygonIndex(index)}
|
onMouseEnter={() => setHoveredPolygonIndex(index)}
|
||||||
onMouseLeave={() => setHoveredPolygonIndex(null)}
|
onMouseLeave={() => setHoveredPolygonIndex(null)}
|
||||||
@ -341,7 +341,7 @@ export default function PolygonItem({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center ${
|
className={`flex min-w-0 items-center ${
|
||||||
hoveredPolygonIndex === index
|
hoveredPolygonIndex === index
|
||||||
? "text-primary"
|
? "text-primary"
|
||||||
: "text-primary-variant"
|
: "text-primary-variant"
|
||||||
@ -359,7 +359,7 @@ export default function PolygonItem({
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={handleToggleEnabled}
|
onClick={handleToggleEnabled}
|
||||||
disabled={isLoading || polygon.enabled_in_config === false}
|
disabled={isLoading || polygon.enabled_in_config === false}
|
||||||
className="mr-2 cursor-pointer border-none bg-transparent p-0 transition-opacity hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50"
|
className="mr-2 shrink-0 cursor-pointer border-none bg-transparent p-0 transition-opacity hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<PolygonItemIcon
|
<PolygonItemIcon
|
||||||
className="size-5"
|
className="size-5"
|
||||||
@ -469,7 +469,15 @@ export default function PolygonItem({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isMobile && hoveredPolygonIndex === index && (
|
{!isMobile && hoveredPolygonIndex === index && (
|
||||||
<div className="flex flex-row items-center gap-2">
|
<div
|
||||||
|
className="absolute inset-y-0 right-0 flex flex-row items-center gap-2 rounded-r-lg pl-8 pr-1"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
polygon.color.length === 3
|
||||||
|
? `linear-gradient(to right, transparent 0%, rgba(${polygon.color[2]},${polygon.color[1]},${polygon.color[0]},0.85) 40%)`
|
||||||
|
: "linear-gradient(to right, transparent 0%, rgba(220,0,0,0.85) 40%)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<IconWrapper
|
<IconWrapper
|
||||||
|
|||||||
@ -64,6 +64,9 @@ export default function MasksAndZonesView({
|
|||||||
);
|
);
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined);
|
const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined);
|
||||||
|
const editPaneRef = useRef(editPane);
|
||||||
|
editPaneRef.current = editPane;
|
||||||
|
const prevScaledRef = useRef<{ w: number; h: number } | null>(null);
|
||||||
const [activeLine, setActiveLine] = useState<number | undefined>();
|
const [activeLine, setActiveLine] = useState<number | undefined>();
|
||||||
const [snapPoints, setSnapPoints] = useState(false);
|
const [snapPoints, setSnapPoints] = useState(false);
|
||||||
|
|
||||||
@ -350,12 +353,36 @@ export default function MasksAndZonesView({
|
|||||||
...globalObjectMasks,
|
...globalObjectMasks,
|
||||||
...objectMasks,
|
...objectMasks,
|
||||||
]);
|
]);
|
||||||
setEditingPolygons([
|
// Don't overwrite editingPolygons during editing – layout shifts
|
||||||
...zones,
|
// from switching to the edit pane can trigger a resize which
|
||||||
...motionMasks,
|
// recalculates scaledWidth/scaledHeight and would discard the
|
||||||
...globalObjectMasks,
|
// newly-added polygon. Instead, rescale existing points
|
||||||
...objectMasks,
|
// proportionally.
|
||||||
]);
|
if (editPaneRef.current === undefined) {
|
||||||
|
setEditingPolygons([
|
||||||
|
...zones,
|
||||||
|
...motionMasks,
|
||||||
|
...globalObjectMasks,
|
||||||
|
...objectMasks,
|
||||||
|
]);
|
||||||
|
} else if (
|
||||||
|
prevScaledRef.current &&
|
||||||
|
(prevScaledRef.current.w !== scaledWidth ||
|
||||||
|
prevScaledRef.current.h !== scaledHeight)
|
||||||
|
) {
|
||||||
|
const prevW = prevScaledRef.current.w;
|
||||||
|
const prevH = prevScaledRef.current.h;
|
||||||
|
setEditingPolygons((prev) =>
|
||||||
|
prev.map((poly) => ({
|
||||||
|
...poly,
|
||||||
|
points: poly.points.map(([x, y]) => [
|
||||||
|
(x / prevW) * scaledWidth,
|
||||||
|
(y / prevH) * scaledHeight,
|
||||||
|
]),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
prevScaledRef.current = { w: scaledWidth, h: scaledHeight };
|
||||||
}
|
}
|
||||||
// we know that these deps are correct
|
// we know that these deps are correct
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@ -431,7 +458,7 @@ export default function MasksAndZonesView({
|
|||||||
{cameraConfig && editingPolygons && (
|
{cameraConfig && editingPolygons && (
|
||||||
<div className="flex size-full flex-col md:flex-row">
|
<div className="flex size-full flex-col md:flex-row">
|
||||||
<Toaster position="top-center" closeButton={true} />
|
<Toaster position="top-center" closeButton={true} />
|
||||||
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12">
|
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12 md:min-w-0 md:shrink-0">
|
||||||
{editPane == "zone" && (
|
{editPane == "zone" && (
|
||||||
<ZoneEditPane
|
<ZoneEditPane
|
||||||
polygons={editingPolygons}
|
polygons={editingPolygons}
|
||||||
@ -707,7 +734,7 @@ export default function MasksAndZonesView({
|
|||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex max-h-[50%] md:h-dvh md:max-h-full md:w-7/12 md:grow",
|
"flex max-h-[50%] min-w-0 md:h-dvh md:max-h-full md:w-7/12 md:grow",
|
||||||
isDesktop && "md:mr-3",
|
isDesktop && "md:mr-3",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user