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>>; setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
onError?: (error: LivePlayerError) => void; onError?: (error: LivePlayerError) => void;
onResetLiveMode?: () => void; onResetLiveMode?: () => void;
contentTransform?: {
scale: number;
positionX: number;
positionY: number;
};
}; };
export default function LivePlayer({ export default function LivePlayer({
@ -76,6 +81,7 @@ export default function LivePlayer({
setFullResolution, setFullResolution,
onError, onError,
onResetLiveMode, onResetLiveMode,
contentTransform,
}: LivePlayerProps) { }: LivePlayerProps) {
const { t } = useTranslation(["components/player"]); const { t } = useTranslation(["components/player"]);
@ -371,7 +377,41 @@ export default function LivePlayer({
lowerClassName="md:rounded-2xl" 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} {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 && {cameraEnabled &&
!offline && !offline &&
(!showStillWithoutActivity || isReEnabling) && (!showStillWithoutActivity || isReEnabling) &&
@ -429,27 +469,6 @@ export default function LivePlayer({
</div> </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 && ( {offline && inDashboard && (
<> <>
<div className="absolute inset-0 rounded-lg bg-black/50 md:rounded-2xl" /> <div className="absolute inset-0 rounded-lg bg-black/50 md:rounded-2xl" />

View File

@ -514,7 +514,8 @@ export default function DraggableGridLayout({
cursorX, cursorX,
cursorY, cursorY,
); );
const content = event.currentTarget.firstElementChild as HTMLElement | null; const content = event.currentTarget
.firstElementChild as HTMLElement | null;
const persisted = toPersistedCameraZoomState(next, { const persisted = toPersistedCameraZoomState(next, {
viewportWidth: bounds.width, viewportWidth: bounds.width,
viewportHeight: bounds.height, viewportHeight: bounds.height,
@ -786,13 +787,6 @@ export default function DraggableGridLayout({
} }
}} }}
onWheel={(event) => handleCardWheelZoom(camera.name, event)} 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 <LivePlayer
key={camera.name} key={camera.name}
@ -804,6 +798,7 @@ export default function DraggableGridLayout({
alwaysShowCameraName={displayCameraNames} alwaysShowCameraName={displayCameraNames}
useWebGL={useWebGL} useWebGL={useWebGL}
cameraRef={cameraRef} cameraRef={cameraRef}
contentTransform={zoomTransform}
className={cn( className={cn(
"draggable-live-grid-mse-cover size-full rounded-lg bg-black md:rounded-2xl", "draggable-live-grid-mse-cover size-full rounded-lg bg-black md:rounded-2xl",
camera.ui?.rotate && camera.ui?.rotate &&
@ -840,7 +835,6 @@ export default function DraggableGridLayout({
volume={volumeStates[camera.name]} volume={volumeStates[camera.name]}
/> />
</div> </div>
</div>
{isEditMode && showCircles && <CornerCircles />} {isEditMode && showCircles && <CornerCircles />}
</GridLiveContextMenu> </GridLiveContextMenu>
); );