Skip to content

Commit

Permalink
refactor(home): animation optimisation
Browse files Browse the repository at this point in the history
  • Loading branch information
royschut committed Oct 24, 2024
1 parent cec2c1f commit 20df811
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@

@include responsive.mobile-and-small-tablet() {
height: calc(67vh + 56px);
-webkit-mask-image: linear-gradient(to top, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 80%);
mask-image: linear-gradient(to top, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 80%);
-webkit-mask-image: linear-gradient(to top, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 75%, rgba(0,0,0,0.5) 90%);
mask-image: linear-gradient(to top, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 75%, rgba(0,0,0,0.5) 90%);
}
}
.image {
Expand Down
60 changes: 26 additions & 34 deletions packages/ui-react/src/components/FeaturedShelf/FeaturedShelf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,69 +61,61 @@ const FeaturedShelf = ({ playlist, loading = false, error = null }: Props) => {
const slideLeft = () => slideTo(index - 1);
const slideRight = () => slideTo(index + 1);

const transitioningRef = React.useRef(false);
const handlingTransitionEnd = React.useRef(false);

// Background animation takes longest, so it leads our animation flow
const handleBackgroundAnimationEnd: TransitionEventHandler = () => {
if (transitioningRef.current) return;
if (handlingTransitionEnd.current) return;
if (animation?.phase !== 'start') return;

transitioningRef.current = true;
setAnimation((current) => ({ ...current, phase: 'end' }));
handlingTransitionEnd.current = true; // Prevent multiple calls from different animations

setTimeout(() => {
setAnimation(null);
setIndex(nextIndex);
transitioningRef.current = false;
}, 1); // Next render
setAnimation((current) => ({ ...current, phase: 'end' }));
setTimeout(() => {
setAnimation(null);
setIndex(nextIndex);
handlingTransitionEnd.current = false;
}, 1); // Next render
}, 250); // Difference between shortest and longest animation
};

const item = playlist.playlist[index];
const leftItem = index - 1 >= 0 ? playlist.playlist[index - 1] : null;
const rightItem = index + 1 < playlist.playlist.length ? playlist.playlist[index + 1] : null;

// Background animation
const isAnimating = animation?.phase === 'start' || animation?.phase === 'end';
const directionFactor = animation?.direction === 'left' ? 1 : animation?.direction === 'right' ? -1 : 0;

const backgroundX = {
left: 50,
right: -50,
};
const translateX = isAnimating && animation?.direction ? backgroundX[animation.direction] : 0;
// Background animation
const backgroundX = 40;
const backgroundCurrentStyle: CSSProperties = {
transform: `scale(1.2) translateX(${translateX}px)`,
transform: `scale(1.2) translateX(${isAnimating ? backgroundX * directionFactor : 0}px)`,
opacity: isAnimating ? 0 : 1,
transition: isAnimating ? 'opacity 0.3s ease-out, transform 0.3s ease-out' : 'none',
transition: isAnimating ? 'opacity 0.1s ease-out, transform 0.3s ease-in' : 'none',
};
const translateXAlt = animation?.direction === 'left' ? -50 : animation?.direction === 'right' ? 50 : 0;
const backgroundAltStyle: CSSProperties = {
transform: `scale(1.2) translateX(${animation?.phase === 'initial' ? translateXAlt : 0}px)`,
transform: `scale(1.2) translateX(${animation?.phase === 'initial' ? backgroundX * directionFactor * -1 : 0}px)`,
opacity: isAnimating ? 1 : 0,
transition: isAnimating ? 'opacity 0.3s ease-out, transform 0.3s ease-out' : 'none',
};

// Metadata animation
const metadataX = {
left: 70,
right: -70,
};
const distanceMetadata = 70;
const defaultTransition = 'opacity 0.2s ease-out, left 0.2s ease-out, right 0.2s ease-out';
const left = isAnimating && animation?.direction ? metadataX[animation.direction] : 0;
const left = 60;
const metadataCurrentStyle: CSSProperties = {
left: left,
left: isAnimating && animation?.direction ? left * directionFactor : 0,
opacity: isAnimating ? 0 : 1,
transition: isAnimating ? defaultTransition : 'none',
transition: isAnimating ? 'opacity 0.15s ease-out, left 0.15s ease-out' : 'none',
pointerEvents: isAnimating ? 'none' : 'initial',
};

const distanceAlt = animation?.direction === 'left' ? -distanceMetadata : animation?.direction === 'right' ? distanceMetadata : 0;
const metadataAltStyle: CSSProperties = {
left: animation?.phase === 'initial' ? distanceAlt : 0,
left: animation?.phase === 'initial' ? left * directionFactor * -1 : 0,
opacity: isAnimating ? 1 : 0,
transition: isAnimating ? defaultTransition : 'none',
transition: isAnimating ? 'opacity 0.2s ease-out, left 0.2s ease-out' : 'none',
pointerEvents: 'none',
};

const item = playlist.playlist[index];
const leftItem = index - 1 >= 0 ? playlist.playlist[index - 1] : null;
const rightItem = index + 1 < playlist.playlist.length ? playlist.playlist[index + 1] : null;

const renderedItem = animation?.phase !== 'end' ? item : animation?.direction === 'right' ? rightItem : leftItem;
const altItem = animation?.direction === 'right' ? rightItem : leftItem;

Expand Down

0 comments on commit 20df811

Please sign in to comment.