From f0f37649925e03e1e94c7fd5352f7277c36af7e8 Mon Sep 17 00:00:00 2001 From: Paul Armstrong Date: Mon, 25 Jan 2021 09:49:00 -0800 Subject: [PATCH] fix(web): make camera latest.jpg responsive --- web/src/CameraMap.jsx | 23 ++++++++--- web/src/Cameras.jsx | 4 +- .../components/AutoUpdatingCameraImage.jsx | 11 +----- web/src/components/CameraImage.jsx | 38 +++++++++++++++++++ web/src/components/Switch.jsx | 10 ++--- 5 files changed, 63 insertions(+), 23 deletions(-) create mode 100644 web/src/components/CameraImage.jsx diff --git a/web/src/CameraMap.jsx b/web/src/CameraMap.jsx index b84a8137c..ae11afb18 100644 --- a/web/src/CameraMap.jsx +++ b/web/src/CameraMap.jsx @@ -1,6 +1,7 @@ import { h } from 'preact'; import Box from './components/Box'; import Button from './components/Button'; +import CameraImage from './components/CameraImage'; import Heading from './components/Heading'; import Switch from './components/Switch'; import { route } from 'preact-router'; @@ -27,14 +28,26 @@ export default function CameraMasks({ camera, url }) { zones, } = cameraConfig; + const resizeObserver = useMemo( + () => + new ResizeObserver((entries) => { + window.requestAnimationFrame(() => { + if (Array.isArray(entries) && entries.length) { + const scaledWidth = entries[0].contentRect.width; + const scale = scaledWidth / width; + setImageScale(scale); + } + }); + }), + [camera, width, setImageScale] + ); + useEffect(() => { if (!imageRef.current) { return; } - const scaledWidth = imageRef.current.width; - const scale = scaledWidth / width; - setImageScale(scale); - }, [imageRef.current, setImageScale]); + resizeObserver.observe(imageRef.current); + }, [resizeObserver, imageRef.current]); const [motionMaskPoints, setMotionMaskPoints] = useState( Array.isArray(motionMask) @@ -226,7 +239,7 @@ ${Object.keys(objectMaskPoints)
- + {name} - + ); } diff --git a/web/src/components/AutoUpdatingCameraImage.jsx b/web/src/components/AutoUpdatingCameraImage.jsx index 8c5f984fe..244aa8a85 100644 --- a/web/src/components/AutoUpdatingCameraImage.jsx +++ b/web/src/components/AutoUpdatingCameraImage.jsx @@ -1,11 +1,10 @@ import { h } from 'preact'; +import CameraImage from './CameraImage'; import { ApiHost, Config } from '../context'; import { useCallback, useEffect, useContext, useState } from 'preact/hooks'; export default function AutoUpdatingCameraImage({ camera, searchParams }) { - const config = useContext(Config); const apiHost = useContext(ApiHost); - const cameraConfig = config.cameras[camera]; const [key, setKey] = useState(Date.now()); useEffect(() => { @@ -17,11 +16,5 @@ export default function AutoUpdatingCameraImage({ camera, searchParams }) { }; }, [key, searchParams]); - return ( - {`Auto-updating - ); + return ; } diff --git a/web/src/components/CameraImage.jsx b/web/src/components/CameraImage.jsx new file mode 100644 index 000000000..4db1be169 --- /dev/null +++ b/web/src/components/CameraImage.jsx @@ -0,0 +1,38 @@ +import { h } from 'preact'; +import { ApiHost, Config } from '../context'; +import { useCallback, useEffect, useContext, useState } from 'preact/hooks'; + +export default function CameraImage({ camera, searchParams = '', imageRef }) { + const config = useContext(Config); + const apiHost = useContext(ApiHost); + const { name, width, height } = config.cameras[camera]; + + const aspectRatio = width / height; + const innerWidth = parseInt(window.innerWidth, 10); + + const responsiveWidths = [640, 768, 1024, 1280]; + if (innerWidth > responsiveWidths[responsiveWidths.length - 1]) { + responsiveWidths.push(innerWidth); + } + + const src = `${apiHost}/api/${camera}/latest.jpg`; + const { srcset, sizes } = responsiveWidths.reduce( + (memo, w, i) => { + memo.srcset.push(`${src}?h=${Math.ceil(w / aspectRatio)}&${searchParams} ${w}w`); + memo.sizes.push(`(max-width: ${w}) ${Math.ceil((w / innerWidth) * 100)}vw`); + return memo; + }, + { srcset: [], sizes: [] } + ); + + return ( + {name} + ); +} diff --git a/web/src/components/Switch.jsx b/web/src/components/Switch.jsx index 9c687c1de..54f57f02f 100644 --- a/web/src/components/Switch.jsx +++ b/web/src/components/Switch.jsx @@ -2,13 +2,9 @@ import { h } from 'preact'; import { useCallback, useState } from 'preact/hooks'; export default function Switch({ checked, label, id, onChange }) { - const handleChange = useCallback( - (event) => { - console.log(event.target.checked, !checked); - onChange(id, !checked); - }, - [id, onChange, checked] - ); + const handleChange = useCallback(() => { + onChange(id, !checked); + }, [id, onChange, checked]); return (