mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-18 06:08:22 +03:00
Fix grid live zoom so overlays stay anchored
This commit is contained in:
parent
6af6468899
commit
6940713054
@ -51,6 +51,11 @@ type LivePlayerProps = {
|
||||
setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
||||
onError?: (error: LivePlayerError) => void;
|
||||
onResetLiveMode?: () => void;
|
||||
contentTransform?: {
|
||||
scale: number;
|
||||
positionX: number;
|
||||
positionY: number;
|
||||
};
|
||||
};
|
||||
|
||||
export default function LivePlayer({
|
||||
@ -76,6 +81,7 @@ export default function LivePlayer({
|
||||
setFullResolution,
|
||||
onError,
|
||||
onResetLiveMode,
|
||||
contentTransform,
|
||||
}: LivePlayerProps) {
|
||||
const { t } = useTranslation(["components/player"]);
|
||||
|
||||
@ -371,7 +377,41 @@ export default function LivePlayer({
|
||||
lowerClassName="md:rounded-2xl"
|
||||
/>
|
||||
)}
|
||||
{player}
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={
|
||||
contentTransform
|
||||
? {
|
||||
transform: `translate(${contentTransform.positionX}px, ${contentTransform.positionY}px) scale(${contentTransform.scale})`,
|
||||
transformOrigin: "0 0",
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{player}
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"absolute inset-0 w-full",
|
||||
showStillWithoutActivity &&
|
||||
!liveReady &&
|
||||
!isReEnabling &&
|
||||
cameraEnabled
|
||||
? "visible"
|
||||
: "invisible",
|
||||
)}
|
||||
>
|
||||
<AutoUpdatingCameraImage
|
||||
className="pointer-events-none size-full"
|
||||
cameraClasses="relative size-full flex justify-center"
|
||||
camera={cameraConfig.name}
|
||||
showFps={false}
|
||||
reloadInterval={stillReloadInterval}
|
||||
periodicCache
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{cameraEnabled &&
|
||||
!offline &&
|
||||
(!showStillWithoutActivity || isReEnabling) &&
|
||||
@ -429,27 +469,6 @@ export default function LivePlayer({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"absolute inset-0 w-full",
|
||||
showStillWithoutActivity &&
|
||||
!liveReady &&
|
||||
!isReEnabling &&
|
||||
cameraEnabled
|
||||
? "visible"
|
||||
: "invisible",
|
||||
)}
|
||||
>
|
||||
<AutoUpdatingCameraImage
|
||||
className="pointer-events-none size-full"
|
||||
cameraClasses="relative size-full flex justify-center"
|
||||
camera={cameraConfig.name}
|
||||
showFps={false}
|
||||
reloadInterval={stillReloadInterval}
|
||||
periodicCache
|
||||
/>
|
||||
</div>
|
||||
|
||||
{offline && inDashboard && (
|
||||
<>
|
||||
<div className="absolute inset-0 rounded-lg bg-black/50 md:rounded-2xl" />
|
||||
|
||||
@ -514,7 +514,8 @@ export default function DraggableGridLayout({
|
||||
cursorX,
|
||||
cursorY,
|
||||
);
|
||||
const content = event.currentTarget.firstElementChild as HTMLElement | null;
|
||||
const content = event.currentTarget
|
||||
.firstElementChild as HTMLElement | null;
|
||||
const persisted = toPersistedCameraZoomState(next, {
|
||||
viewportWidth: bounds.width,
|
||||
viewportHeight: bounds.height,
|
||||
@ -787,59 +788,52 @@ export default function DraggableGridLayout({
|
||||
}}
|
||||
onWheel={(event) => handleCardWheelZoom(camera.name, event)}
|
||||
>
|
||||
<div
|
||||
className="size-full"
|
||||
style={{
|
||||
transform: `translate(${zoomTransform.positionX}px, ${zoomTransform.positionY}px) scale(${zoomTransform.scale})`,
|
||||
transformOrigin: "0 0",
|
||||
<LivePlayer
|
||||
key={camera.name}
|
||||
streamName={streamName}
|
||||
autoLive={autoLive ?? globalAutoLive}
|
||||
showStillWithoutActivity={
|
||||
showStillWithoutActivity ?? true
|
||||
}
|
||||
alwaysShowCameraName={displayCameraNames}
|
||||
useWebGL={useWebGL}
|
||||
cameraRef={cameraRef}
|
||||
contentTransform={zoomTransform}
|
||||
className={cn(
|
||||
"draggable-live-grid-mse-cover size-full rounded-lg bg-black md:rounded-2xl",
|
||||
camera.ui?.rotate &&
|
||||
"draggable-live-grid-rotated [--frigate-mse-grid-rotated:1] [--frigate-mse-grid-rotation:rotate(90deg)]",
|
||||
isEditMode &&
|
||||
showCircles &&
|
||||
"outline-2 outline-muted-foreground hover:cursor-grab hover:outline-4 active:cursor-grabbing",
|
||||
)}
|
||||
windowVisible={
|
||||
windowVisible && visibleCameras.includes(camera.name)
|
||||
}
|
||||
cameraConfig={camera}
|
||||
preferredLiveMode={
|
||||
preferredLiveModes[camera.name] ?? "mse"
|
||||
}
|
||||
playInBackground={false}
|
||||
showStats={statsStates[camera.name] ?? true}
|
||||
onClick={() => {
|
||||
!isEditMode && onSelectCamera(camera.name);
|
||||
}}
|
||||
>
|
||||
<LivePlayer
|
||||
key={camera.name}
|
||||
streamName={streamName}
|
||||
autoLive={autoLive ?? globalAutoLive}
|
||||
showStillWithoutActivity={
|
||||
showStillWithoutActivity ?? true
|
||||
}
|
||||
alwaysShowCameraName={displayCameraNames}
|
||||
useWebGL={useWebGL}
|
||||
cameraRef={cameraRef}
|
||||
className={cn(
|
||||
"draggable-live-grid-mse-cover size-full rounded-lg bg-black md:rounded-2xl",
|
||||
camera.ui?.rotate &&
|
||||
"draggable-live-grid-rotated [--frigate-mse-grid-rotated:1] [--frigate-mse-grid-rotation:rotate(90deg)]",
|
||||
isEditMode &&
|
||||
showCircles &&
|
||||
"outline-2 outline-muted-foreground hover:cursor-grab hover:outline-4 active:cursor-grabbing",
|
||||
)}
|
||||
windowVisible={
|
||||
windowVisible && visibleCameras.includes(camera.name)
|
||||
}
|
||||
cameraConfig={camera}
|
||||
preferredLiveMode={
|
||||
preferredLiveModes[camera.name] ?? "mse"
|
||||
}
|
||||
playInBackground={false}
|
||||
showStats={statsStates[camera.name] ?? true}
|
||||
onClick={() => {
|
||||
!isEditMode && onSelectCamera(camera.name);
|
||||
}}
|
||||
onError={(e) => {
|
||||
setPreferredLiveModes((prevModes) => {
|
||||
const newModes = { ...prevModes };
|
||||
if (e === "mse-decode") {
|
||||
delete newModes[camera.name];
|
||||
}
|
||||
return newModes;
|
||||
});
|
||||
}}
|
||||
onResetLiveMode={() =>
|
||||
resetPreferredLiveMode(camera.name)
|
||||
}
|
||||
playAudio={audioStates[camera.name]}
|
||||
volume={volumeStates[camera.name]}
|
||||
/>
|
||||
</div>
|
||||
onError={(e) => {
|
||||
setPreferredLiveModes((prevModes) => {
|
||||
const newModes = { ...prevModes };
|
||||
if (e === "mse-decode") {
|
||||
delete newModes[camera.name];
|
||||
}
|
||||
return newModes;
|
||||
});
|
||||
}}
|
||||
onResetLiveMode={() =>
|
||||
resetPreferredLiveMode(camera.name)
|
||||
}
|
||||
playAudio={audioStates[camera.name]}
|
||||
volume={volumeStates[camera.name]}
|
||||
/>
|
||||
</div>
|
||||
{isEditMode && showCircles && <CornerCircles />}
|
||||
</GridLiveContextMenu>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user