我正在使用 react.js、Typescript、chakra 和动画框架。 有一个 MotionSwipe 组件,可让您向右和向左滑动。可以拖动它来滑动子元素的 Box。 我们希望 Box 不仅可以通过拖动来向右或向左移动,还可以通过按下按钮来向右或向左移动。 在按下按钮时调用的 onClickSwipe 函数中,我执行了 animateCardSwipe 函数使其向右滑动。但是,动画太快了,我看不到。我想减慢按下按钮时 Box 向右移动的动画。
import { Button,Box } from '@chakra-ui/react';
import { PanInfo, useMotionValue, useTransform } from 'framer-motion';
import { NextPage } from 'next';
import { MotionSwipe } from 'components/MotionSwipe';
import React, { useState } from 'react';
const Component: React.VoidFunctionComponent = () => {
const [cards, setCards] = useState([
{ text: 'Up or down', background: 'red' },
{ text: 'Left or right', background: 'green' },
{ text: 'Swipe me!', background: 'gray' },
]);
const [dragStart, setDragStart] = useState<{ axis: string | null; animation: { x: number; y: number } }>({
axis: null,
animation: { x: 0, y: 0 },
});
const x = useMotionValue(0);
const y = useMotionValue(0);
const onDirectionLock = (axis: string | null) => setDragStart({ ...dragStart, axis: axis });
const animateCardSwipe = (animation: { x: number; y: number }) => {
setDragStart({ ...dragStart, animation });
setTimeout(() => {
setDragStart({ axis: null, animation: { x: 0, y: 0 } });
x.set(0);
y.set(0);
setCards([...cards.slice(0, cards.length - 1)]);
}, 200);
};
const onDragEnd = (info: PanInfo) => {
if (dragStart.axis === 'x') {
if (info.offset.x >= 400) animateCardSwipe({ x: 300, y: 0 });
else if (info.offset.x <= -400) animateCardSwipe({ x: -300, y: 0 });
} else {
if (info.offset.y >= 100) animateCardSwipe({ x: 0, y: 100 });
else if (info.offset.y <= -100) animateCardSwipe({ x: 0, y: -100 });
}
};
const rotate = useTransform(x, [-700, 700], [-90, 90]);
const onClickSwipe = () => {
animateCardSwipe({ x: 500, y: 0 });
};
return (
<>
<Box display="flex" justifyContent="center" width="300px">
{cards.map((card, index) =>
index === cards.length - 1 ? (
<MotionSwipe
animate={dragStart.animation}
card={card}
key={index}
onDirectionLock={(axis: string) => onDirectionLock(axis)}
onDragEnd={(e: MouseEvent, info: PanInfo) => onDragEnd(info)}
style={{ x, y, zIndex: index, rotate: rotate }}
>
<Box background={card.background} height="300px" width="300px"></Box>
</MotionSwipe>
) : (
<MotionSwipe
card={card}
key={index}
style={{
zIndex: index,
}}
>
<Box background={card.background} height="300px" width="300px"></Box>
</MotionSwipe>
),
)}
</Box>
<Button onClick={onClickSwipe}>
○
</Button>
<Button>✖︎</Button>
</>
);
};
const SwipeBox: NextPage = () => {
return <Component />;
};
export default SwipeBox;
interface Props {
animate?: { x: number; y: number };
onDirectionLock?: (axis: 'x' | 'y') => void;
onDragEnd?: (e: MouseEvent, info: PanInfo) => void;
style: { x?: MotionValue; y?: MotionValue; zIndex: number; rotate?: MotionValue };
card: { text: string; background: string };
}
export const MotionSwipe: React.FunctionComponent<Props> = (props) => {
return (
<MotionBox
animate={props.animate}
background="white"
borderTopRadius="8px"
className="card"
display="grid"
drag
dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
dragDirectionLock
left={0}
onDirectionLock={props.onDirectionLock}
onDragEnd={props.onDragEnd}
placeItems="center center"
position="absolute"
style={{ ...props.style }}
top={0}
transition={{ ease: [0.6, 0.05, -0.01, 0.9], duration: 3 }}
>
{props.children}
</MotionBox>
);
};
答案 0 :(得分:0)
是的,速度快的时候没问题。如何更改:
useState
变量以检查按钮是否被按下。
例如:const [pressed, setPressed] = useState(false);
setPressed(true)
pressed(true)
,您添加一些 transition
或 animation
道具和 duration
。如果您没有 duration
,您的元素将在按钮点击后立即触发。