From 1f56cc1af6cd80490ccf3aafb6f06c8afa5136d2 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Mon, 24 May 2021 00:28:05 +0300 Subject: [PATCH] Media Viewer: Fix animation glitches when closing (#1102) --- .../mediaViewer/helpers/ghostAnimation.ts | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/components/mediaViewer/helpers/ghostAnimation.ts b/src/components/mediaViewer/helpers/ghostAnimation.ts index a667ef23f..ec944891a 100644 --- a/src/components/mediaViewer/helpers/ghostAnimation.ts +++ b/src/components/mediaViewer/helpers/ghostAnimation.ts @@ -88,7 +88,9 @@ export function animateOpening( setTimeout(() => { requestAnimationFrame(() => { - document.body.removeChild(ghost); + if (document.body.contains(ghost)) { + document.body.removeChild(ghost); + } document.body.classList.remove('ghost-animating'); }); }, ANIMATION_DURATION + ANIMATION_END_DELAY); @@ -148,21 +150,50 @@ export function animateClosing(origin: MediaViewerOrigin, bestImageData: string, } } - const ghost = createGhost(bestImageData || toImage, origin === MediaViewerOrigin.ProfileAvatar); - applyStyles(ghost, { - top: `${toTop}px`, - left: `${toLeft}px`, - width: `${toWidth}px`, - height: `${toHeight}px`, - transform: `translate3d(${fromTranslateX}px, ${fromTranslateY}px, 0) scale(${fromScaleX}, ${fromScaleY})`, - }); + const existingGhost = document.getElementsByClassName('ghost')[0] as HTMLDivElement; + + const ghost = existingGhost || createGhost(bestImageData || toImage, origin === MediaViewerOrigin.ProfileAvatar); + if (!existingGhost) { + applyStyles(ghost, { + top: `${toTop}px`, + left: `${toLeft}px`, + width: `${toWidth}px`, + height: `${toHeight}px`, + transform: `translate3d(${fromTranslateX}px, ${fromTranslateY}px, 0) scale(${fromScaleX}, ${fromScaleY})`, + }); + } requestAnimationFrame(() => { + if (existingGhost) { + const { + top, + left, + width, + height, + } = existingGhost.getBoundingClientRect(); + const scaleX = width / toWidth; + const scaleY = height / toHeight; + + applyStyles(ghost, { + transition: 'none', + top: `${toTop}px`, + left: `${toLeft}px`, + transformOrigin: 'top left', + transform: `translate3d(${left - toLeft}px, ${top - toTop}px, 0) scale(${scaleX}, ${scaleY})`, + width: `${toWidth}px`, + height: `${toHeight}px`, + }); + } document.body.classList.add('ghost-animating'); - document.body.appendChild(ghost); + if (!existingGhost) document.body.appendChild(ghost); requestAnimationFrame(() => { + if (existingGhost) { + existingGhost.style.transition = ''; + } + ghost.style.transform = ''; + if (shouldFadeOut) { ghost.style.opacity = '0'; } @@ -171,7 +202,9 @@ export function animateClosing(origin: MediaViewerOrigin, bestImageData: string, setTimeout(() => { requestAnimationFrame(() => { - document.body.removeChild(ghost); + if (document.body.contains(ghost)) { + document.body.removeChild(ghost); + } document.body.classList.remove('ghost-animating'); }); }, ANIMATION_DURATION + ANIMATION_END_DELAY);