From ffe817388a25f46bead5037aa7ce3071b4e1fca3 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sun, 19 Mar 2023 19:10:56 +0100 Subject: [PATCH] scrollToActive fixed --- src/video/components/popouts/PopoutUtils.tsx | 42 +++++++++++--------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/video/components/popouts/PopoutUtils.tsx b/src/video/components/popouts/PopoutUtils.tsx index 3573a86f..a56d1a91 100644 --- a/src/video/components/popouts/PopoutUtils.tsx +++ b/src/video/components/popouts/PopoutUtils.tsx @@ -43,6 +43,8 @@ export function ScrollToActive(props: ScrollToActiveProps) { const ref = createRef(); const inited = useRef(false); + const SAFE_OFFSET = 30; + // Scroll to "active" child on first load (AKA mount except React dumb) useEffect(() => { if (inited.current) return; @@ -61,27 +63,31 @@ export function ScrollToActive(props: ScrollToActiveProps) { wrapper?.querySelector(".active"); if (wrapper && active) { - let activeYPositionCentered = 0; - const setActiveYPositionCentered = () => { - activeYPositionCentered = - active.getBoundingClientRect().top - - wrapper.getBoundingClientRect().top + - active.offsetHeight / 2; + let wrapperHeight = 0; + let activePos = 0; + let activeHeight = 0; + let wrapperScroll = 0; + + const getCoords = () => { + const activeRect = active.getBoundingClientRect(); + const wrapperRect = wrapper.getBoundingClientRect(); + wrapperHeight = wrapperRect.height; + activeHeight = activeRect.height; + activePos = activeRect.top - wrapperRect.top + wrapper.scrollTop; + wrapperScroll = wrapper.scrollTop; }; - setActiveYPositionCentered(); + getCoords(); - if (activeYPositionCentered >= wrapper.offsetHeight / 2) { - // Check if the active element is below the vertical center line, then scroll it into center + const isVisible = + activePos + activeHeight < + wrapperScroll + wrapperHeight - SAFE_OFFSET || + activePos > wrapperScroll + SAFE_OFFSET; + if (isVisible) { + const activeMiddlePos = activePos + activeHeight / 2; // pos of middle of active element + const viewMiddle = wrapperHeight / 2; // half of the available height + const pos = activeMiddlePos - viewMiddle; wrapper.scrollTo({ - top: activeYPositionCentered - wrapper.offsetHeight / 2, - }); - } - - setActiveYPositionCentered(); - if (activeYPositionCentered > wrapper.offsetHeight / 2) { - // If the element is over the vertical center line, scroll to the end - wrapper.scrollTo({ - top: wrapper.scrollHeight, + top: pos, }); } }