我有一个动画,它能很好地将项目从右向左移动。当单击后退按钮时,我想做相反的事情,类似于在移动应用程序中从导航堆栈中弹出视图。我的代码如下,当单击按钮时,如何使动画向后运行?我使用的是React 17.0.2和React弹簧9.2.3。
import React, { useState, useCallback, CSSProperties, useEffect } from "react";
import {
useTransition,
animated,
AnimatedProps,
useSpringRef,
} from "react-spring";
import styles from "../styles/components/carousel.module.css";
const Carousel: React.FC = () => {
const [index, set] = useState(0);
const onClick = useCallback(() => set((state) => (state + 1) % 6), []);
const transRef = useSpringRef();
const transitions = useTransition(index, {
ref: transRef,
keys: null,
from: { opacity: 0, transform: "translate3d(100%,0,0)" },
enter: { opacity: 1, transform: "translate3d(0%,0,0)" },
leave: { opacity: 0, transform: "translate3d(-50%,0,0)" },
});
useEffect(() => {
transRef.start();
}, [index, transRef]);
const pageContent: { text: string; color: string }[] = [
{ text: "one", color: "lightpink" },
{ text: "two", color: "lightblue" },
{ text: "three", color: "lightgreen" },
];
const pages: ((
props: AnimatedProps<{ style: CSSProperties }>
) => React.ReactElement)[] = pageContent.map((obj) => {
return function createAnimatedDiv({ style }) {
return (
<animated.div style={{ ...style, background: obj.color }}>
{obj.text}
</animated.div>
);
};
});
const onBackClicked = useCallback(() => set((state) => (state - 1) % 6), []);
return (
<>
<button onClick={onBackClicked}>Back</button>
<div className={`flex fill ${styles.container}`} onClick={onClick}>
{transitions((style, i) => {
const Page = pages[i];
return <Page style={style} />;
})}
</div>
</>
);
};
export default Carousel;
首先,您需要知道动画的方向。为此,您可以使用usePrevious挂钩并比较当前和以前的索引。然后,根据方向,您可以返回不同的转换配置。
type Direction = 'left' | 'right' | null;
// helpers
const getDirection = (index: number, previousIndex: number): Direction => {
if (index === previousIndex) {
return null;
}
return index > previousIndex ? 'right' : 'left';
};
const getTransitionConfig = (direction: Direction): Parameters<typeof useTransition>[1] => {
if (direction === 'right') {
return {
from: { opacity: 0, left: -300 },
enter: { opacity: 1, left: 0 },
leave: { opacity: 0, left: 300 },
};
}
if (direction === 'left') {
return {
from: { opacity: 0, left: 300 },
enter: { opacity: 1, left: 0 },
leave: { opacity: 0, left: -300 },
};
}
return {};
};
// component
const [index, set] = useState(0);
const previousIndex = usePrevious(index);
const animationDirection = getDirection(index, previousIndex);
const transitionConfig = useMemo(() => ({
ref: transRef,
keys: null,
...getTransitionConfig(animationDirection)
}), [animationDirection, getTransitionConfig]);
const transitions = useTransition(index, transitionConfig);
// ...
为了简单起见,我使用了left
属性。当然,您可以使用transform
。