Merge pull request #34 from ibs0d/codex/fix-zoom-behavior-in-draggablegridlayout

Apply grid zoom to video layer only and keep overlays anchored
This commit is contained in:
ibs0d 2026-03-09 12:14:16 +11:00 committed by GitHub
commit e36d12d9f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 88 additions and 75 deletions

View File

@ -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"
/>
)}
<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" />

View File

@ -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,
@ -786,13 +787,6 @@ 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}
@ -804,6 +798,7 @@ export default function DraggableGridLayout({
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 &&
@ -840,7 +835,6 @@ export default function DraggableGridLayout({
volume={volumeStates[camera.name]}
/>
</div>
</div>
{isEditMode && showCircles && <CornerCircles />}
</GridLiveContextMenu>
);