diff --git a/web/src/components/CameraImage.jsx b/web/src/components/CameraImage.jsx
index a609ac916..52f537834 100644
--- a/web/src/components/CameraImage.jsx
+++ b/web/src/components/CameraImage.jsx
@@ -4,7 +4,7 @@ import { useApiHost, useConfig } from '../api';
import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks';
import { useResizeObserver } from '../hooks';
-export default function CameraImage({ camera, onload, searchParams = '' }) {
+export default function CameraImage({ camera, onload, searchParams = '', stretch = false }) {
const { data: config } = useConfig();
const apiHost = useApiHost();
const [hasLoaded, setHasLoaded] = useState(false);
@@ -15,11 +15,10 @@ export default function CameraImage({ camera, onload, searchParams = '' }) {
const { name, width, height } = config.cameras[camera];
const aspectRatio = width / height;
- const scaledHeight = useMemo(() => Math.min(Math.ceil(availableWidth / aspectRatio), height), [
- availableWidth,
- aspectRatio,
- height,
- ]);
+ const scaledHeight = useMemo(() => {
+ const scaledHeight = Math.floor(availableWidth / aspectRatio);
+ return stretch ? scaledHeight : Math.min(scaledHeight, height);
+ }, [availableWidth, aspectRatio, height, stretch]);
const scaledWidth = useMemo(() => Math.ceil(scaledHeight * aspectRatio), [scaledHeight, aspectRatio]);
const img = useMemo(() => new Image(), []);
diff --git a/web/src/components/__tests__/CameraImage.test.jsx b/web/src/components/__tests__/CameraImage.test.jsx
index 7228a1137..3ee208438 100644
--- a/web/src/components/__tests__/CameraImage.test.jsx
+++ b/web/src/components/__tests__/CameraImage.test.jsx
@@ -25,12 +25,18 @@ describe('CameraImage', () => {
render();
expect(screen.queryByLabelText('Loading…')).toBeInTheDocument();
- expect(screen.queryByTestId('cameraimage-canvas')).toMatchInlineSnapshot(`
-
- `);
+ const canvas = screen.queryByTestId('cameraimage-canvas');
+ expect(canvas).toHaveAttribute('height', '405');
+ expect(canvas).toHaveAttribute('width', '720');
+ });
+
+ test('allows camera image to stretch to available space', async () => {
+ jest.spyOn(Hooks, 'useResizeObserver').mockReturnValueOnce([{ width: 1400 }]);
+
+ render();
+ expect(screen.queryByLabelText('Loading…')).toBeInTheDocument();
+ const canvas = screen.queryByTestId('cameraimage-canvas');
+ expect(canvas).toHaveAttribute('height', '787');
+ expect(canvas).toHaveAttribute('width', '1400');
});
});
diff --git a/web/src/routes/Cameras.jsx b/web/src/routes/Cameras.jsx
index 3895193db..6dc0a00cc 100644
--- a/web/src/routes/Cameras.jsx
+++ b/web/src/routes/Cameras.jsx
@@ -23,5 +23,5 @@ function Camera({ name }) {
const href = `/cameras/${name}`;
const buttons = useMemo(() => [{ name: 'Events', href: `/events?camera=${name}` }], [name]);
- return } />;
+ return } />;
}