Untitled
unknown
plain_text
2 years ago
5.4 kB
20
Indexable
export type Player = {
/// Plays the animation
play: () => void;
/// Sets the direction of play
setDirection: (direction: "forward" | "reverse") => void;
/// Pauses the animation
pause: () => void;
/// Stops animation playback
stop: () => void;
};
export const useAnimation = () => {
const lottieRef = useRef<Player | null>(null);
const play = () => {
lottieRef.current?.play();
};
const setDirection = (direction: "forward" | "reverse") => {
console.log("setDirection in useAnimation");
lottieRef.current?.setDirection(direction);
};
const pause = () => {
lottieRef.current?.pause();
};
const stop = () => {
lottieRef.current?.stop();
};
lottieRef.current = {
pause,
play,
setDirection,
stop,
};
return {
control: lottieRef,
pause,
play,
setDirection,
stop,
};
};
export const Animation = ({
animateOnViewportEnter,
aspectRatio,
delay = 0,
height = "auto",
loop = false,
maxHeight,
maxWidth,
name,
width = "100%",
control,
}: AnimationProps) => {
const ref = useRef<HTMLDivElement | null>(null);
const internalLottieRef = useRef<LottiePlayer | 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") => {
console.log("setDirection in Animation");
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 = "";
internalLottieRef.current = lottie;
const data = await import(`@ds/assets/animations/${name}.json`);
internalLottieRef.current.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>
);
};
export const Face = ({ name, onClick, children }: FaceProps) => {
const { control, play, setDirection, pause } = useAnimation();
const handleMouseEnter = () => {
console.log("handleMouseEnter")
setDirection("forward");
play();
};
const handleMouseLeave = () => {
pause();
setDirection("reverse");
play();
};
const handleClick = () => {
onClick?.();
};
return (
<BoxRipple
alignItems="center"
display="flex"
flexDirection="column"
gap="space12"
onClick={handleClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
width={56}
>
<Animation
control={control}
height={48}
name={`AnimationSurvey${name}HoverOn48x48`}
width={48}
/>
<Text variant="standard-bold">{children}</Text>
</BoxRipple>
);
};
jak używam powyzszego komponentu Face, w ten sposób
to dostaje błąd
Uncaught RangeError: Maximum call stack size exceeded
at Object.setDirection
i w konsoli widzę że "setDirection in useAnimation"
zostało wywołane kilka tysięcy razy, skąd ten błąd? bo z kolei "handleMouseEnter" zostało zalogowane raz
Editor is loading...
Leave a Comment