From bd17e7d824af9fa8a26f3098dbb063f0a75294cb Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 30 Jun 2023 06:15:19 -0600 Subject: [PATCH] Show object attributes when hovering or tapping timeline bounding box (#6879) * Show overlay when hovering on timeline box * Make it work with mobile too * Fix lint * Fix ratio * Update web/src/components/TimelineEventOverlay.jsx Co-authored-by: Blake Blackshear * Show overlay when hovering on timeline box * Make it work with mobile too * Fix lint * Fix ratio * Remove label and make overlay respect selected theme --------- Co-authored-by: Blake Blackshear --- web/src/components/TimelineEventOverlay.jsx | 65 +++++++++++++++++++++ web/src/routes/Events.jsx | 22 ++----- 2 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 web/src/components/TimelineEventOverlay.jsx diff --git a/web/src/components/TimelineEventOverlay.jsx b/web/src/components/TimelineEventOverlay.jsx new file mode 100644 index 000000000..717b3809a --- /dev/null +++ b/web/src/components/TimelineEventOverlay.jsx @@ -0,0 +1,65 @@ +import { Fragment, h } from 'preact'; +import { useState } from 'preact/hooks'; + +export default function TimelineEventOverlay({ eventOverlay, cameraConfig }) { + const boxLeftEdge = Math.round(eventOverlay.data.box[0] * 100); + const boxTopEdge = Math.round(eventOverlay.data.box[1] * 100); + const boxRightEdge = Math.round((1 - eventOverlay.data.box[2] - eventOverlay.data.box[0]) * 100); + const boxBottomEdge = Math.round((1 - eventOverlay.data.box[3] - eventOverlay.data.box[1]) * 100); + + const [isHovering, setIsHovering] = useState(false); + const getHoverStyle = () => { + if (boxLeftEdge < 15) { + // show object stats on right side + return { + left: `${boxLeftEdge + eventOverlay.data.box[2] * 100 + 1}%`, + top: `${boxTopEdge}%`, + }; + } + + return { + right: `${boxRightEdge + eventOverlay.data.box[2] * 100 + 1}%`, + top: `${boxTopEdge}%`, + }; + }; + + const getObjectArea = () => { + const width = eventOverlay.data.box[2] * cameraConfig.detect.width; + const height = eventOverlay.data.box[3] * cameraConfig.detect.height; + return Math.round(width * height); + }; + + const getObjectRatio = () => { + const width = eventOverlay.data.box[2] * cameraConfig.detect.width; + const height = eventOverlay.data.box[3] * cameraConfig.detect.height; + return Math.round(100 * (width / height)) / 100; + }; + + return ( + +
setIsHovering(true)} + onMouseLeave={() => setIsHovering(false)} + onTouchStart={() => setIsHovering(true)} + onTouchEnd={() => setIsHovering(false)} + style={{ + left: `${boxLeftEdge}%`, + top: `${boxTopEdge}%`, + right: `${boxRightEdge}%`, + bottom: `${boxBottomEdge}%`, + }} + > + {eventOverlay.class_type == 'entered_zone' ? ( +
+ ) : null} +
+ {isHovering && ( +
+
{`Area: ${getObjectArea()} px`}
+
{`Ratio: ${getObjectRatio()}`}
+
+ )} + + ); +} diff --git a/web/src/routes/Events.jsx b/web/src/routes/Events.jsx index 8de35413b..9d503cb8b 100644 --- a/web/src/routes/Events.jsx +++ b/web/src/routes/Events.jsx @@ -29,6 +29,7 @@ import { formatUnixTimestampToDateTime, getDurationFromTimestamps } from '../uti import TimeAgo from '../components/TimeAgo'; import Timepicker from '../components/TimePicker'; import TimelineSummary from '../components/TimelineSummary'; +import TimelineEventOverlay from '../components/TimelineEventOverlay'; const API_LIMIT = 25; @@ -717,23 +718,10 @@ export default function Events({ path, ...props }) { }} > {eventOverlay ? ( -
- {eventOverlay.class_type == 'entered_zone' ? ( -
- ) : null} -
+ ) : null}