Untitled
unknown
plain_text
a year ago
3.6 kB
13
Indexable
import React, { RefObject, useEffect, useImperativeHandle, useRef } from "react";
import { AnimationName } from "@ds/assets/animations";
import { SxProps } from "@mui/material";
import { AnimationItem } from "lottie-web/build/player/lottie_light";
import { InView } from "react-intersection-observer";
import { Box } from "../box";
import { Player } from "./use-animation";
export type AnimationProps = {
animateOnViewportEnter?: boolean;
aspectRatio?: string;
delay?: number;
height?: number | string;
maxHeight?: number | string;
name: AnimationName;
width?: number | string;
maxWidth?: number | string;
loop?: boolean;
control?: RefObject<Player>;
onAnimationComplete?: () => void;
};
export const Animation = ({
animateOnViewportEnter,
aspectRatio,
delay = 0,
height = "auto",
loop = false,
maxHeight,
maxWidth,
name,
width = "100%",
control,
onAnimationComplete,
}: AnimationProps) => {
const ref = useRef<HTMLDivElement | null>(null);
const internalLottieRef = useRef<AnimationItem | null>(null);
const handleViewEnter = (inView: boolean) => {
if (inView) {
internalLottieRef.current?.play();
}
};
useImperativeHandle(
control,
() => {
return {
pause: () => {
internalLottieRef.current?.pause();
},
play: () => {
internalLottieRef.current?.play();
},
setDirection: (direction: "forward" | "reverse") => {
internalLottieRef.current?.setDirection(direction === "forward" ? 1 : -1);
},
stop: () => {
internalLottieRef.current?.stop();
},
};
},
[],
);
useEffect(() => {
const loadLottie = async () => {
const { default: lottie } = await import(
/* webpackChunkName: "lottie-web" */ "lottie-web/build/player/lottie_light"
);
lottie.setLocationHref(window.location.href);
if (!ref.current) {
return;
}
ref.current.innerHTML = "";
const data = await import(`@ds/assets/animations/${name}.json`);
internalLottieRef.current = lottie.loadAnimation({
animationData: data,
autoplay: false,
container: ref.current,
loop,
renderer: "svg",
});
const play = () => internalLottieRef.current?.play();
if (delay) {
setTimeout(play, delay);
}
if (!animateOnViewportEnter && !control) {
play();
}
};
loadLottie();
}, [animateOnViewportEnter, delay, control, loop, name]);
const containerStyles: SxProps = {
aspectRatio,
maxHeight,
maxWidth,
svg: {
height: `${typeof height === "number" ? `${height}px` : height} !important`,
width: `${typeof width === "number" ? `${width}px` : width} !important`,
},
};
const content = <Box aria-hidden={true} display="flex" ref={ref} sx={containerStyles} />;
if (!animateOnViewportEnter) {
return content;
}
return (
<InView onChange={handleViewEnter} triggerOnce={true}>
{content}
</InView>
);
};
Editor is loading...
Leave a Comment